diff --git a/.htaccess b/.htaccess index 71a5cf708dbc5..e07a564bc0ab6 100644 --- a/.htaccess +++ b/.htaccess @@ -37,29 +37,6 @@ DirectoryIndex index.php - -############################################ -## adjust memory limit - - php_value memory_limit 756M - php_value max_execution_time 18000 - -############################################ -## disable automatic session start -## before autoload was initialized - - php_flag session.auto_start off - -############################################ -## enable resulting html compression - - #php_flag zlib.output_compression on - -########################################### -## disable user agent verification to not break multiple image upload - - php_flag suhosin.session.cryptua off - ############################################ ## adjust memory limit diff --git a/README.md b/README.md index 91f2ed19fb453..ba194266f691a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,20 @@ -[![Open Source Helpers](https://www.codetriage.com/magento/magento2/badges/users.svg)](https://www.codetriage.com/magento/magento2) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/magento/magento2?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Crowdin](https://d322cqt584bo4o.cloudfront.net/magento-2/localized.svg)](https://crowdin.com/project/magento-2) +

+ + Magento + +

+

+

+ + Open Source Helpers + + + Gitter + + + Crowdin + +

## Welcome Welcome to Magento 2 installation! We're glad you chose to install Magento 2, a cutting-edge, feature-rich eCommerce solution that gets results. diff --git a/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml b/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml similarity index 92% rename from app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml rename to app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml index 5cf7be8a6fe11..89896d05bbe42 100644 --- a/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml +++ b/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml b/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml similarity index 56% rename from app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml rename to app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml index d9f5e5dbcb106..fc66f9fb0ef74 100644 --- a/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml +++ b/app/code/Magento/AdminAnalytics/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml @@ -8,7 +8,10 @@ - + + + + diff --git a/app/code/Magento/AdminNotification/Test/Mftf/Test/AdminSystemNotificationNavigateMenuTest.xml b/app/code/Magento/AdminNotification/Test/Mftf/Test/AdminSystemNotificationNavigateMenuTest.xml index 75dceb4028622..81ad2858d5901 100644 --- a/app/code/Magento/AdminNotification/Test/Mftf/Test/AdminSystemNotificationNavigateMenuTest.xml +++ b/app/code/Magento/AdminNotification/Test/Mftf/Test/AdminSystemNotificationNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index 5da7adf794215..285ddb1f99e29 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -3,14 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Analytics\ReportXml; use Magento\Analytics\ReportXml\DB\SelectBuilderFactory; use Magento\Framework\App\CacheInterface; +use Magento\Framework\DB\Select; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\Serializer\Json; /** * Creates Query object according to configuration + * * Factory for @see \Magento\Analytics\ReportXml\Query */ class QueryFactory @@ -45,6 +49,11 @@ class QueryFactory */ private $selectHydrator; + /** + * @var Json + */ + private $jsonSerializer; + /** * QueryFactory constructor. * @@ -54,6 +63,7 @@ class QueryFactory * @param SelectBuilderFactory $selectBuilderFactory * @param Config $config * @param array $assemblers + * @param Json $jsonSerializer */ public function __construct( CacheInterface $queryCache, @@ -61,7 +71,8 @@ public function __construct( ObjectManagerInterface $objectManager, SelectBuilderFactory $selectBuilderFactory, Config $config, - array $assemblers + array $assemblers, + Json $jsonSerializer ) { $this->config = $config; $this->selectBuilderFactory = $selectBuilderFactory; @@ -69,6 +80,7 @@ public function __construct( $this->queryCache = $queryCache; $this->objectManager = $objectManager; $this->selectHydrator = $selectHydrator; + $this->jsonSerializer = $jsonSerializer; } /** @@ -101,14 +113,10 @@ private function constructQuery($queryName) $selectBuilder = $assembler->assemble($selectBuilder, $queryConfig); } $select = $selectBuilder->create(); - return $this->objectManager->create( - Query::class, - [ - 'select' => $select, - 'selectHydrator' => $this->selectHydrator, - 'connectionName' => $selectBuilder->getConnectionName(), - 'config' => $queryConfig - ] + return $this->createQueryObject( + $select, + $selectBuilder->getConnectionName(), + $queryConfig ); } @@ -122,19 +130,42 @@ public function create($queryName) { $cached = $this->queryCache->load($queryName); if ($cached) { - $queryData = json_decode($cached, true); - return $this->objectManager->create( - Query::class, - [ - 'select' => $this->selectHydrator->recreate($queryData['select_parts']), - 'selectHydrator' => $this->selectHydrator, - 'connectionName' => $queryData['connectionName'], - 'config' => $queryData['config'] - ] + $queryData = $this->jsonSerializer->unserialize($cached); + return $this->createQueryObject( + $this->selectHydrator->recreate($queryData['select_parts']), + $queryData['connectionName'], + $queryData['config'] ); } $query = $this->constructQuery($queryName); - $this->queryCache->save(json_encode($query), $queryName); + $this->queryCache->save( + $this->jsonSerializer->serialize($query), + $queryName + ); return $query; } + + /** + * Create query class using objectmanger + * + * @param Select $select + * @param string $connection + * @param array $queryConfig + * @return Query + */ + private function createQueryObject( + Select $select, + string $connection, + array $queryConfig + ) { + return $this->objectManager->create( + Query::class, + [ + 'select' => $select, + 'selectHydrator' => $this->selectHydrator, + 'connectionName' => $connection, + 'config' => $queryConfig + ] + ); + } } diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml index e660a2eb8d428..5da7ccd3c9823 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingButtonTest.xml @@ -25,7 +25,7 @@ - + @@ -35,4 +35,4 @@ - \ No newline at end of file + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingNavigateMenuTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingNavigateMenuTest.xml index d400bcf5f22fc..c742248b32cc3 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingNavigateMenuTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminAdvancedReportingNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationBlankIndustryTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationBlankIndustryTest.xml index 914cb59b64e4e..17d463030d91c 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationBlankIndustryTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationBlankIndustryTest.xml @@ -18,9 +18,9 @@ - + - + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationEnableDisableAnalyticsTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationEnableDisableAnalyticsTest.xml index 1c1a3b27b06af..b03488c240604 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationEnableDisableAnalyticsTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationEnableDisableAnalyticsTest.xml @@ -18,9 +18,9 @@ - + - + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationIndustryTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationIndustryTest.xml index bb682c4468012..c19fddc6aa0ce 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationIndustryTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationIndustryTest.xml @@ -19,7 +19,7 @@ - + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationPermissionTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationPermissionTest.xml index 58e809ec45c4a..93ee464a17efa 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationPermissionTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationPermissionTest.xml @@ -21,10 +21,10 @@ - + - + @@ -51,7 +51,7 @@ - + diff --git a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationTimeToSendDataTest.xml b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationTimeToSendDataTest.xml index 8ebd8cb594bee..6231b17c17b02 100644 --- a/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationTimeToSendDataTest.xml +++ b/app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationTimeToSendDataTest.xml @@ -19,9 +19,9 @@ - + - + diff --git a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php index 9a3805a50f167..032ef1e107825 100644 --- a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php +++ b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php @@ -3,161 +3,171 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\Analytics\Test\Unit\ReportXml; +use Magento\Analytics\ReportXml\QueryFactory; +use Magento\Analytics\ReportXml\Query; +use Magento\Analytics\ReportXml\Config; +use Magento\Framework\DB\Select; +use Magento\Analytics\ReportXml\DB\Assembler\AssemblerInterface; +use Magento\Framework\App\CacheInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Analytics\ReportXml\SelectHydrator; +use Magento\Analytics\ReportXml\DB\SelectBuilder; +use Magento\Analytics\ReportXml\DB\SelectBuilderFactory; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + /** * A unit test for testing of the query factory. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class QueryFactoryTest extends \PHPUnit\Framework\TestCase +class QueryFactoryTest extends TestCase { + const STUB_QUERY_NAME = 'test_query'; + const STUB_CONNECTION = 'default'; + /** - * @var \Magento\Analytics\ReportXml\QueryFactory + * @var QueryFactory */ private $subject; /** - * @var \Magento\Analytics\ReportXml\Query|\PHPUnit_Framework_MockObject_MockObject + * @var Query|MockObject */ private $queryMock; /** - * @var \Magento\Analytics\ReportXml\Config|\PHPUnit_Framework_MockObject_MockObject + * @var Config|MockObject */ private $configMock; /** - * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject + * @var Select|MockObject */ private $selectMock; /** - * @var \Magento\Analytics\ReportXml\DB\Assembler\AssemblerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var AssemblerInterface|MockObject */ private $assemblerMock; /** - * @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CacheInterface|MockObject */ private $queryCacheMock; /** - * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerInterface|MockObject */ private $objectManagerMock; /** - * @var \Magento\Analytics\ReportXml\SelectHydrator|\PHPUnit_Framework_MockObject_MockObject + * @var SelectHydrator|MockObject */ private $selectHydratorMock; /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var ObjectManagerHelper */ private $objectManagerHelper; /** - * @var \Magento\Analytics\ReportXml\DB\SelectBuilderFactory|\PHPUnit_Framework_MockObject_MockObject + * @var SelectBuilderFactory|MockObject */ private $selectBuilderFactoryMock; + /** + * @var Json|MockObject + */ + private $jsonSerializerMock; + /** * @return void */ - protected function setUp() + protected function setUp(): void { - $this->queryMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\Query::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->configMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\Config::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->selectMock = $this->getMockBuilder( - \Magento\Framework\DB\Select::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->assemblerMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\DB\Assembler\AssemblerInterface::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->queryCacheMock = $this->getMockBuilder( - \Magento\Framework\App\CacheInterface::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManagerMock = $this->getMockBuilder( - \Magento\Framework\ObjectManagerInterface::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->selectHydratorMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\SelectHydrator::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->selectBuilderFactoryMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\DB\SelectBuilderFactory::class - ) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManagerHelper = - new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->queryMock = $this->getMockBuilder(Query::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->assemblerMock = $this->getMockBuilder(AssemblerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->queryCacheMock = $this->getMockBuilder(CacheInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->selectHydratorMock = $this->getMockBuilder(SelectHydrator::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->selectBuilderFactoryMock = $this->getMockBuilder(SelectBuilderFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->jsonSerializerMock = $this->createMock(Json::class); + + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->subject = $this->objectManagerHelper->getObject( - \Magento\Analytics\ReportXml\QueryFactory::class, + QueryFactory::class, [ - 'config' => $this->configMock, - 'selectBuilderFactory' => $this->selectBuilderFactoryMock, - 'assemblers' => [$this->assemblerMock], 'queryCache' => $this->queryCacheMock, + 'selectHydrator' => $this->selectHydratorMock, 'objectManager' => $this->objectManagerMock, - 'selectHydrator' => $this->selectHydratorMock + 'selectBuilderFactory' => $this->selectBuilderFactoryMock, + 'config' => $this->configMock, + 'assemblers' => [$this->assemblerMock], + 'jsonSerializer' => $this->jsonSerializerMock ] ); } /** + * Test create() if query cached + * * @return void + * @dataProvider queryDataProvider */ - public function testCreateCached() + public function testCreateIfQueryCached(array $queryDataMock, string $jsonEncodeData): void { - $queryName = 'test_query'; + $queryConfigMock = $queryDataMock['config']; + $queryName = $queryConfigMock['name']; $this->queryCacheMock->expects($this->any()) ->method('load') ->with($queryName) - ->willReturn('{"connectionName":"sales","config":{},"select_parts":{}}'); + ->willReturn($jsonEncodeData); + + $this->jsonSerializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($queryDataMock); $this->selectHydratorMock->expects($this->any()) ->method('recreate') ->with([]) ->willReturn($this->selectMock); - $this->objectManagerMock->expects($this->once()) - ->method('create') - ->with( - \Magento\Analytics\ReportXml\Query::class, - [ - 'select' => $this->selectMock, - 'selectHydrator' => $this->selectHydratorMock, - 'connectionName' => 'sales', - 'config' => [] - ] - ) - ->willReturn($this->queryMock); + $this->createQueryObjectMock($queryDataMock); $this->queryCacheMock->expects($this->never()) ->method('save'); @@ -169,22 +179,19 @@ public function testCreateCached() } /** + * Test create() if query not cached + * * @return void + * @dataProvider queryDataProvider */ - public function testCreateNotCached() + public function testCreateIfQueryNotCached(array $queryDataMock, string $jsonEncodeData): void { - $queryName = 'test_query'; - - $queryConfigMock = [ - 'name' => 'test_query', - 'connection' => 'sales' - ]; + $queryConfigMock = $queryDataMock['config']; + $queryName = $queryConfigMock['name']; - $selectBuilderMock = $this->getMockBuilder( - \Magento\Analytics\ReportXml\DB\SelectBuilder::class - ) - ->disableOriginalConstructor() - ->getMock(); + $selectBuilderMock = $this->getMockBuilder(SelectBuilder::class) + ->disableOriginalConstructor() + ->getMock(); $selectBuilderMock->expects($this->once()) ->method('setConnectionName') ->with($queryConfigMock['connection']); @@ -214,26 +221,65 @@ public function testCreateNotCached() ->with($selectBuilderMock, $queryConfigMock) ->willReturn($selectBuilderMock); + $this->createQueryObjectMock($queryDataMock); + + $this->jsonSerializerMock->expects($this->once()) + ->method('serialize') + ->willReturn($jsonEncodeData); + + $this->queryCacheMock->expects($this->once()) + ->method('save') + ->with($jsonEncodeData, $queryName); + + $this->assertEquals( + $this->queryMock, + $this->subject->create($queryName) + ); + } + + /** + * Get Query Data Provider + * + * @return array + */ + public function queryDataProvider(): array + { + return [ + [ + 'getQueryDataMock' => [ + 'connectionName' => self::STUB_CONNECTION, + 'config' => [ + 'name' => self::STUB_QUERY_NAME, + 'connection' => self::STUB_CONNECTION + ], + 'select_parts' => [] + ], + 'getQueryDataJsonEncodeMock' => '{"connectionName":"default",'. + '"config":{"name":"test_query",'. + '"connection":"default"},"select_parts":[]}' + ] + ]; + } + + /** + * ObjectManager Mock with Query class + * + * @param array $queryDataMock + * @return void + */ + private function createQueryObjectMock($queryDataMock): void + { $this->objectManagerMock->expects($this->once()) ->method('create') ->with( - \Magento\Analytics\ReportXml\Query::class, + Query::class, [ 'select' => $this->selectMock, 'selectHydrator' => $this->selectHydratorMock, - 'connectionName' => $queryConfigMock['connection'], - 'config' => $queryConfigMock + 'connectionName' => $queryDataMock['connectionName'], + 'config' => $queryDataMock['config'] ] ) ->willReturn($this->queryMock); - - $this->queryCacheMock->expects($this->once()) - ->method('save') - ->with(json_encode($this->queryMock), $queryName); - - $this->assertEquals( - $this->queryMock, - $this->subject->create($queryName) - ); } } diff --git a/app/code/Magento/Authorization/Model/Acl/Loader/Role.php b/app/code/Magento/Authorization/Model/Acl/Loader/Role.php index a5f8fbd6eefec..e4b1103491230 100644 --- a/app/code/Magento/Authorization/Model/Acl/Loader/Role.php +++ b/app/code/Magento/Authorization/Model/Acl/Loader/Role.php @@ -3,14 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Authorization\Model\Acl\Loader; use Magento\Authorization\Model\Acl\Role\Group as RoleGroup; +use Magento\Authorization\Model\Acl\Role\GroupFactory; use Magento\Authorization\Model\Acl\Role\User as RoleUser; -use Magento\Framework\App\ObjectManager; +use Magento\Authorization\Model\Acl\Role\UserFactory; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\Acl\LoaderInterface; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Serialize\Serializer\Json; -class Role implements \Magento\Framework\Acl\LoaderInterface +/** + * Acl Role Loader + */ +class Role implements LoaderInterface { /** * Cache key for ACL roles cache @@ -18,22 +27,22 @@ class Role implements \Magento\Framework\Acl\LoaderInterface const ACL_ROLES_CACHE_KEY = 'authorization_role_cached_data'; /** - * @var \Magento\Framework\App\ResourceConnection + * @var ResourceConnection */ protected $_resource; /** - * @var \Magento\Authorization\Model\Acl\Role\GroupFactory + * @var GroupFactory */ protected $_groupFactory; /** - * @var \Magento\Authorization\Model\Acl\Role\UserFactory + * @var UserFactory */ protected $_roleFactory; /** - * @var \Magento\Framework\Acl\Data\CacheInterface + * @var CacheInterface */ private $aclDataCache; @@ -48,28 +57,26 @@ class Role implements \Magento\Framework\Acl\LoaderInterface private $cacheKey; /** - * @param \Magento\Authorization\Model\Acl\Role\GroupFactory $groupFactory - * @param \Magento\Authorization\Model\Acl\Role\UserFactory $roleFactory - * @param \Magento\Framework\App\ResourceConnection $resource - * @param \Magento\Framework\Acl\Data\CacheInterface $aclDataCache + * @param GroupFactory $groupFactory + * @param UserFactory $roleFactory + * @param ResourceConnection $resource + * @param CacheInterface $aclDataCache * @param Json $serializer * @param string $cacheKey */ public function __construct( - \Magento\Authorization\Model\Acl\Role\GroupFactory $groupFactory, - \Magento\Authorization\Model\Acl\Role\UserFactory $roleFactory, - \Magento\Framework\App\ResourceConnection $resource, - \Magento\Framework\Acl\Data\CacheInterface $aclDataCache = null, - Json $serializer = null, + GroupFactory $groupFactory, + UserFactory $roleFactory, + ResourceConnection $resource, + CacheInterface $aclDataCache, + Json $serializer, $cacheKey = self::ACL_ROLES_CACHE_KEY ) { - $this->_resource = $resource; $this->_groupFactory = $groupFactory; $this->_roleFactory = $roleFactory; - $this->aclDataCache = $aclDataCache ?: ObjectManager::getInstance()->get( - \Magento\Framework\Acl\Data\CacheInterface::class - ); - $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class); + $this->_resource = $resource; + $this->aclDataCache = $aclDataCache; + $this->serializer = $serializer; $this->cacheKey = $cacheKey; } diff --git a/app/code/Magento/Authorization/Model/Acl/Loader/Rule.php b/app/code/Magento/Authorization/Model/Acl/Loader/Rule.php index 57bdcdbb3d9b8..b8fd974c5da6c 100644 --- a/app/code/Magento/Authorization/Model/Acl/Loader/Rule.php +++ b/app/code/Magento/Authorization/Model/Acl/Loader/Rule.php @@ -3,12 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Authorization\Model\Acl\Loader; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\Acl\LoaderInterface; +use Magento\Framework\Acl\RootResource; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Serialize\Serializer\Json; -class Rule implements \Magento\Framework\Acl\LoaderInterface +/** + * Acl Rule Loader + */ +class Rule implements LoaderInterface { /** * Rules array cache key @@ -16,17 +24,17 @@ class Rule implements \Magento\Framework\Acl\LoaderInterface const ACL_RULE_CACHE_KEY = 'authorization_rule_cached_data'; /** - * @var \Magento\Framework\App\ResourceConnection + * @var ResourceConnection */ protected $_resource; /** - * @var \Magento\Framework\Acl\RootResource + * @var RootResource */ private $_rootResource; /** - * @var \Magento\Framework\Acl\Data\CacheInterface + * @var CacheInterface */ private $aclDataCache; @@ -41,28 +49,26 @@ class Rule implements \Magento\Framework\Acl\LoaderInterface private $cacheKey; /** - * @param \Magento\Framework\Acl\RootResource $rootResource - * @param \Magento\Framework\App\ResourceConnection $resource - * @param array $data - * @param \Magento\Framework\Acl\Data\CacheInterface $aclDataCache + * @param RootResource $rootResource + * @param ResourceConnection $resource + * @param CacheInterface $aclDataCache * @param Json $serializer + * @param array $data * @param string $cacheKey * @SuppressWarnings(PHPMD.UnusedFormalParameter): */ public function __construct( - \Magento\Framework\Acl\RootResource $rootResource, - \Magento\Framework\App\ResourceConnection $resource, + RootResource $rootResource, + ResourceConnection $resource, + CacheInterface $aclDataCache, + Json $serializer, array $data = [], - \Magento\Framework\Acl\Data\CacheInterface $aclDataCache = null, - Json $serializer = null, $cacheKey = self::ACL_RULE_CACHE_KEY ) { - $this->_resource = $resource; $this->_rootResource = $rootResource; - $this->aclDataCache = $aclDataCache ?: ObjectManager::getInstance()->get( - \Magento\Framework\Acl\Data\CacheInterface::class - ); - $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class); + $this->_resource = $resource; + $this->aclDataCache = $aclDataCache; + $this->serializer = $serializer; $this->cacheKey = $cacheKey; } @@ -104,7 +110,7 @@ private function getRulesArray() return $this->serializer->unserialize($rulesCachedData); } - $ruleTable = $this->_resource->getTableName("authorization_rule"); + $ruleTable = $this->_resource->getTableName('authorization_rule'); $connection = $this->_resource->getConnection(); $select = $connection->select() ->from(['r' => $ruleTable]); diff --git a/app/code/Magento/Authorization/Model/ResourceModel/Rules.php b/app/code/Magento/Authorization/Model/ResourceModel/Rules.php index 5e4ae77731a0f..46470d885650b 100644 --- a/app/code/Magento/Authorization/Model/ResourceModel/Rules.php +++ b/app/code/Magento/Authorization/Model/ResourceModel/Rules.php @@ -6,58 +6,63 @@ namespace Magento\Authorization\Model\ResourceModel; -use Magento\Framework\App\ObjectManager; +use Magento\Backend\App\AbstractAction; +use Magento\Framework\Acl\Builder; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\Acl\RootResource; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Psr\Log\LoggerInterface; /** * Admin rule resource model */ -class Rules extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb +class Rules extends AbstractDb { /** * Root ACL resource * - * @var \Magento\Framework\Acl\RootResource + * @var RootResource */ protected $_rootResource; /** - * @var \Magento\Framework\Acl\Builder + * @var Builder */ protected $_aclBuilder; /** - * @var \Psr\Log\LoggerInterface + * @var LoggerInterface */ protected $_logger; /** - * @var \Magento\Framework\Acl\Data\CacheInterface + * @var CacheInterface */ private $aclDataCache; /** - * @param \Magento\Framework\Model\ResourceModel\Db\Context $context - * @param \Magento\Framework\Acl\Builder $aclBuilder - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Acl\RootResource $rootResource + * @param Context $context + * @param Builder $aclBuilder + * @param LoggerInterface $logger + * @param RootResource $rootResource + * @param CacheInterface $aclDataCache * @param string $connectionName - * @param \Magento\Framework\Acl\Data\CacheInterface $aclDataCache */ public function __construct( - \Magento\Framework\Model\ResourceModel\Db\Context $context, - \Magento\Framework\Acl\Builder $aclBuilder, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Acl\RootResource $rootResource, - $connectionName = null, - \Magento\Framework\Acl\Data\CacheInterface $aclDataCache = null + Context $context, + Builder $aclBuilder, + LoggerInterface $logger, + RootResource $rootResource, + CacheInterface $aclDataCache, + $connectionName = null ) { $this->_aclBuilder = $aclBuilder; parent::__construct($context, $connectionName); $this->_rootResource = $rootResource; $this->_logger = $logger; - $this->aclDataCache = $aclDataCache ?: ObjectManager::getInstance()->get( - \Magento\Framework\Acl\Data\CacheInterface::class - ); + $this->aclDataCache = $aclDataCache; } /** @@ -75,7 +80,7 @@ protected function _construct() * * @param \Magento\Authorization\Model\Rules $rule * @return void - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function saveRel(\Magento\Authorization\Model\Rules $rule) { @@ -107,7 +112,7 @@ public function saveRel(\Magento\Authorization\Model\Rules $rule) $connection->insert($this->getMainTable(), $insertData); } else { /** Give basic admin permissions to any admin */ - $postedResources[] = \Magento\Backend\App\AbstractAction::ADMIN_RESOURCE; + $postedResources[] = AbstractAction::ADMIN_RESOURCE; $acl = $this->_aclBuilder->getAcl(); /** @var $resource \Magento\Framework\Acl\AclResource */ foreach ($acl->getResources() as $resourceId) { @@ -125,7 +130,7 @@ public function saveRel(\Magento\Authorization\Model\Rules $rule) $connection->commit(); $this->aclDataCache->clean(); - } catch (\Magento\Framework\Exception\LocalizedException $e) { + } catch (LocalizedException $e) { $connection->rollBack(); throw $e; } catch (\Exception $e) { diff --git a/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RoleTest.php b/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RoleTest.php index a5ae7f8e86a6e..e1841b895dd07 100644 --- a/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RoleTest.php +++ b/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RoleTest.php @@ -3,199 +3,221 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Authorization\Test\Unit\Model\Acl\Loader; -class RoleTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Authorization\Model\Acl\Loader\Role - */ - protected $_model; +use Magento\Authorization\Model\Acl\Loader\Role; +use Magento\Authorization\Model\Acl\Role\GroupFactory; +use Magento\Authorization\Model\Acl\Role\UserFactory; +use Magento\Framework\Acl; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\Pdo\Mysql; +use Magento\Framework\DB\Select; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +/** + * Test class for \Magento\Authorization\Model\Acl\Loader\Role + */ +class RoleTest extends TestCase +{ /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Role */ - protected $_resourceMock; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var GroupFactory|MockObject */ - protected $_adapterMock; + private $groupFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var UserFactory|MockObject */ - protected $_roleFactoryMock; + private $roleFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ResourceConnection|MockObject */ - protected $_groupFactoryMock; + private $resourceMock; /** - * @var \Magento\Framework\Acl\Data\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CacheInterface|MockObject */ private $aclDataCacheMock; /** - * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit_Framework_MockObject_MockObject + * @var Json|MockObject */ private $serializerMock; /** - * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject + * @var Select|MockObject */ private $selectMock; + /** + * @var Mysql|MockObject + */ + private $adapterMock; + + /** + * @inheritDoc + */ protected function setUp() { - $this->_resourceMock = $this->createMock(\Magento\Framework\App\ResourceConnection::class); - $this->_groupFactoryMock = $this->getMockBuilder(\Magento\Authorization\Model\Acl\Role\GroupFactory::class) + $this->groupFactoryMock = $this->getMockBuilder(GroupFactory::class) ->setMethods(['create', 'getModelInstance']) ->disableOriginalConstructor() ->getMock(); - $this->_roleFactoryMock = $this->getMockBuilder(\Magento\Authorization\Model\Acl\Role\UserFactory::class) + $this->roleFactoryMock = $this->getMockBuilder(UserFactory::class) ->setMethods(['create', 'getModelInstance']) ->disableOriginalConstructor() ->getMock(); - - $this->selectMock = $this->createMock(\Magento\Framework\DB\Select::class); - $this->selectMock->expects($this->any()) - ->method('from') - ->will($this->returnValue($this->selectMock)); - - $this->_adapterMock = $this->createMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class); - + $this->resourceMock = $this->createMock(ResourceConnection::class); + $this->aclDataCacheMock = $this->createMock(CacheInterface::class); $this->serializerMock = $this->createPartialMock( - \Magento\Framework\Serialize\Serializer\Json::class, + Json::class, ['serialize', 'unserialize'] ); - $this->serializerMock->expects($this->any()) - ->method('serialize') - ->will( - $this->returnCallback( - function ($value) { - return json_encode($value); - } - ) - ); - $this->serializerMock->expects($this->any()) - ->method('unserialize') - ->will( - $this->returnCallback( - function ($value) { - return json_decode($value, true); - } - ) + $this->serializerMock->method('serialize') + ->willReturnCallback( + static function ($value) { + return json_encode($value); + } ); - $this->aclDataCacheMock = $this->createMock(\Magento\Framework\Acl\Data\CacheInterface::class); + $this->serializerMock->method('unserialize') + ->willReturnCallback( + static function ($value) { + return json_decode($value, true); + } + ); - $this->_model = new \Magento\Authorization\Model\Acl\Loader\Role( - $this->_groupFactoryMock, - $this->_roleFactoryMock, - $this->_resourceMock, - $this->aclDataCacheMock, - $this->serializerMock + $this->selectMock = $this->createMock(Select::class); + $this->selectMock->method('from') + ->willReturn($this->selectMock); + + $this->adapterMock = $this->createMock(Mysql::class); + + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + Role::class, + [ + 'groupFactory' => $this->groupFactoryMock, + 'roleFactory' => $this->roleFactoryMock, + 'resource' => $this->resourceMock, + 'aclDataCache' => $this->aclDataCacheMock, + 'serializer' => $this->serializerMock + ] ); } + /** + * Test populating acl roles with children + */ public function testPopulateAclAddsRolesAndTheirChildren() { - $this->_resourceMock->expects($this->once()) + $this->resourceMock->expects($this->once()) ->method('getTableName') ->with($this->equalTo('authorization_role')) - ->will($this->returnArgument(1)); + ->willReturnArgument(1); - $this->_adapterMock->expects($this->once()) + $this->adapterMock->expects($this->once()) ->method('select') - ->will($this->returnValue($this->selectMock)); + ->willReturn($this->selectMock); - $this->_resourceMock->expects($this->once()) + $this->resourceMock->expects($this->once()) ->method('getConnection') - ->will($this->returnValue($this->_adapterMock)); + ->willReturn($this->adapterMock); - $this->_adapterMock->expects($this->once()) + $this->adapterMock->expects($this->once()) ->method('fetchAll') - ->will( - $this->returnValue( - [ - ['role_id' => 1, 'role_type' => 'G', 'parent_id' => null], - ['role_id' => 2, 'role_type' => 'U', 'parent_id' => 1, 'user_id' => 1], - ] - ) + ->willReturn( + [ + ['role_id' => 1, 'role_type' => 'G', 'parent_id' => null], + ['role_id' => 2, 'role_type' => 'U', 'parent_id' => 1, 'user_id' => 1], + ] ); - $this->_groupFactoryMock->expects($this->once())->method('create')->with(['roleId' => '1']); - $this->_roleFactoryMock->expects($this->once())->method('create')->with(['roleId' => '2']); + $this->groupFactoryMock->expects($this->once())->method('create')->with(['roleId' => '1']); + $this->roleFactoryMock->expects($this->once())->method('create')->with(['roleId' => '2']); - $aclMock = $this->createMock(\Magento\Framework\Acl::class); + $aclMock = $this->createMock(Acl::class); $aclMock->expects($this->at(0))->method('addRole')->with($this->anything(), null); $aclMock->expects($this->at(2))->method('addRole')->with($this->anything(), '1'); - $this->_model->populateAcl($aclMock); + $this->model->populateAcl($aclMock); } + /** + * Test populating acl role with multiple parents + */ public function testPopulateAclAddsMultipleParents() { - $this->_resourceMock->expects($this->once()) + $this->resourceMock->expects($this->once()) ->method('getTableName') ->with($this->equalTo('authorization_role')) - ->will($this->returnArgument(1)); + ->willReturnArgument(1); - $this->_adapterMock->expects($this->once()) + $this->adapterMock->expects($this->once()) ->method('select') - ->will($this->returnValue($this->selectMock)); + ->willReturn($this->selectMock); - $this->_resourceMock->expects($this->once()) + $this->resourceMock->expects($this->once()) ->method('getConnection') - ->will($this->returnValue($this->_adapterMock)); + ->willReturn($this->adapterMock); - $this->_adapterMock->expects($this->once()) + $this->adapterMock->expects($this->once()) ->method('fetchAll') - ->will($this->returnValue([['role_id' => 1, 'role_type' => 'U', 'parent_id' => 2, 'user_id' => 3]])); + ->willReturn([['role_id' => 1, 'role_type' => 'U', 'parent_id' => 2, 'user_id' => 3]]); - $this->_roleFactoryMock->expects($this->never())->method('getModelInstance'); - $this->_groupFactoryMock->expects($this->never())->method('getModelInstance'); + $this->roleFactoryMock->expects($this->never())->method('getModelInstance'); + $this->groupFactoryMock->expects($this->never())->method('getModelInstance'); - $aclMock = $this->createMock(\Magento\Framework\Acl::class); - $aclMock->expects($this->at(0))->method('hasRole')->with('1')->will($this->returnValue(true)); + $aclMock = $this->createMock(Acl::class); + $aclMock->expects($this->at(0))->method('hasRole')->with('1')->willReturn(true); $aclMock->expects($this->at(1))->method('addRoleParent')->with('1', '2'); - $this->_model->populateAcl($aclMock); + $this->model->populateAcl($aclMock); } + /** + * Test populating acl role from cache + */ public function testPopulateAclFromCache() { - $this->_resourceMock->expects($this->never())->method('getConnection'); - $this->_resourceMock->expects($this->never())->method('getTableName'); - $this->_adapterMock->expects($this->never())->method('fetchAll'); + $this->resourceMock->expects($this->never())->method('getConnection'); + $this->resourceMock->expects($this->never())->method('getTableName'); + $this->adapterMock->expects($this->never())->method('fetchAll'); $this->aclDataCacheMock->expects($this->once()) ->method('load') - ->with(\Magento\Authorization\Model\Acl\Loader\Role::ACL_ROLES_CACHE_KEY) - ->will( - $this->returnValue( - json_encode( + ->with(Role::ACL_ROLES_CACHE_KEY) + ->willReturn( + json_encode( + [ [ - [ - 'role_id' => 1, - 'role_type' => 'U', - 'parent_id' => 2, - 'user_id' => 3 - ] + 'role_id' => 1, + 'role_type' => 'U', + 'parent_id' => 2, + 'user_id' => 3 ] - ) + ] ) ); - $this->_roleFactoryMock->expects($this->never())->method('getModelInstance'); - $this->_groupFactoryMock->expects($this->never())->method('getModelInstance'); + $this->roleFactoryMock->expects($this->never())->method('getModelInstance'); + $this->groupFactoryMock->expects($this->never())->method('getModelInstance'); - $aclMock = $this->createMock(\Magento\Framework\Acl::class); - $aclMock->expects($this->at(0))->method('hasRole')->with('1')->will($this->returnValue(true)); + $aclMock = $this->createMock(Acl::class); + $aclMock->expects($this->at(0))->method('hasRole')->with('1')->willReturn(true); $aclMock->expects($this->at(1))->method('addRoleParent')->with('1', '2'); - $this->_model->populateAcl($aclMock); + $this->model->populateAcl($aclMock); } } diff --git a/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RuleTest.php b/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RuleTest.php index 51801e1842eff..c7a9b80c6597c 100644 --- a/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RuleTest.php +++ b/app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RuleTest.php @@ -3,105 +3,121 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Authorization\Test\Unit\Model\Acl\Loader; -class RuleTest extends \PHPUnit\Framework\TestCase +use Magento\Authorization\Model\Acl\Loader\Rule; +use Magento\Framework\Acl; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\Acl\RootResource; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test class for \Magento\Authorization\Model\Acl\Loader\Rule + */ +class RuleTest extends TestCase { /** - * @var \Magento\Authorization\Model\Acl\Loader\Rule + * @var Rule */ - protected $_model; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var RootResource */ - protected $_resourceMock; + private $rootResource; /** - * @var \Magento\Framework\Acl\RootResource + * @var ResourceConnection|MockObject */ - protected $_rootResourceMock; + private $resourceMock; /** - * @var \Magento\Framework\Acl\Data\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CacheInterface|MockObject */ private $aclDataCacheMock; /** - * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit_Framework_MockObject_MockObject + * @var Json|MockObject */ private $serializerMock; + /** + * @inheritDoc + */ protected function setUp() { - $this->_resourceMock = $this->createPartialMock( - \Magento\Framework\App\ResourceConnection::class, + $this->rootResource = new RootResource('Magento_Backend::all'); + $this->resourceMock = $this->createPartialMock( + ResourceConnection::class, ['getTable', 'getConnection'] ); + $this->aclDataCacheMock = $this->createMock(CacheInterface::class); $this->serializerMock = $this->createPartialMock( - \Magento\Framework\Serialize\Serializer\Json::class, + Json::class, ['serialize', 'unserialize'] ); - $this->serializerMock->expects($this->any()) - ->method('serialize') - ->will( - $this->returnCallback( - function ($value) { - return json_encode($value); - } - ) - ); - $this->serializerMock->expects($this->any()) - ->method('unserialize') - ->will( - $this->returnCallback( - function ($value) { - return json_decode($value, true); - } - ) + $this->serializerMock->method('serialize') + ->willReturnCallback( + static function ($value) { + return json_encode($value); + } ); - $this->aclDataCacheMock = $this->createMock(\Magento\Framework\Acl\Data\CacheInterface::class); + $this->serializerMock->method('unserialize') + ->willReturnCallback( + static function ($value) { + return json_decode($value, true); + } + ); - $this->_rootResourceMock = new \Magento\Framework\Acl\RootResource('Magento_Backend::all'); - $this->_model = new \Magento\Authorization\Model\Acl\Loader\Rule( - $this->_rootResourceMock, - $this->_resourceMock, - [], - $this->aclDataCacheMock, - $this->serializerMock + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + Rule::class, + [ + 'rootResource' => $this->rootResource, + 'resource' => $this->resourceMock, + 'aclDataCache' => $this->aclDataCacheMock, + 'serializer' => $this->serializerMock + ] ); } + /** + * Test populating acl rule from cache + */ public function testPopulateAclFromCache() { - $this->_resourceMock->expects($this->never())->method('getTable'); - $this->_resourceMock->expects($this->never()) + $this->resourceMock->expects($this->never())->method('getTable'); + $this->resourceMock->expects($this->never()) ->method('getConnection'); $this->aclDataCacheMock->expects($this->once()) ->method('load') - ->with(\Magento\Authorization\Model\Acl\Loader\Rule::ACL_RULE_CACHE_KEY) - ->will( - $this->returnValue( - json_encode( - [ - ['role_id' => 1, 'resource_id' => 'Magento_Backend::all', 'permission' => 'allow'], - ['role_id' => 2, 'resource_id' => 1, 'permission' => 'allow'], - ['role_id' => 3, 'resource_id' => 1, 'permission' => 'deny'], - ] - ) + ->with(Rule::ACL_RULE_CACHE_KEY) + ->willReturn( + json_encode( + [ + ['role_id' => 1, 'resource_id' => 'Magento_Backend::all', 'permission' => 'allow'], + ['role_id' => 2, 'resource_id' => 1, 'permission' => 'allow'], + ['role_id' => 3, 'resource_id' => 1, 'permission' => 'deny'], + ] ) ); - $aclMock = $this->createMock(\Magento\Framework\Acl::class); - $aclMock->expects($this->any())->method('has')->will($this->returnValue(true)); + $aclMock = $this->createMock(Acl::class); + $aclMock->method('has')->willReturn(true); $aclMock->expects($this->at(1))->method('allow')->with('1', null, null); $aclMock->expects($this->at(2))->method('allow')->with('1', 'Magento_Backend::all', null); $aclMock->expects($this->at(4))->method('allow')->with('2', 1, null); $aclMock->expects($this->at(6))->method('deny')->with('3', 1, null); - $this->_model->populateAcl($aclMock); + $this->model->populateAcl($aclMock); } } diff --git a/app/code/Magento/Authorization/Test/Unit/Model/ResourceModel/RulesTest.php b/app/code/Magento/Authorization/Test/Unit/Model/ResourceModel/RulesTest.php index 260691608537e..36cd789042f43 100644 --- a/app/code/Magento/Authorization/Test/Unit/Model/ResourceModel/RulesTest.php +++ b/app/code/Magento/Authorization/Test/Unit/Model/ResourceModel/RulesTest.php @@ -3,9 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Authorization\Test\Unit\Model\ResourceModel; +use Magento\Authorization\Model\ResourceModel\Rules; +use Magento\Framework\Acl\Builder; +use Magento\Framework\Acl\Data\CacheInterface; +use Magento\Framework\Acl\RootResource; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Magento\Framework\Phrase; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + /** * Unit test for Rules resource model. * @@ -14,7 +28,7 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class RulesTest extends \PHPUnit\Framework\TestCase +class RulesTest extends TestCase { /** * Test constants @@ -22,121 +36,125 @@ class RulesTest extends \PHPUnit\Framework\TestCase const TEST_ROLE_ID = 13; /** - * @var \Magento\Authorization\Model\ResourceModel\Rules + * @var Rules */ private $model; /** - * @var \Magento\Framework\Model\ResourceModel\Db\Context|\PHPUnit_Framework_MockObject_MockObject + * @var Context|MockObject */ private $contextMock; /** - * @var \Magento\Framework\Acl\Builder|\PHPUnit_Framework_MockObject_MockObject + * @var Builder|MockObject */ private $aclBuilderMock; /** - * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LoggerInterface|MockObject */ private $loggerMock; /** - * @var \Magento\Framework\Acl\RootResource|\PHPUnit_Framework_MockObject_MockObject + * @var RootResource|MockObject */ private $rootResourceMock; /** - * @var \Magento\Framework\Acl\Data\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CacheInterface|MockObject */ private $aclDataCacheMock; /** - * @var \Magento\Framework\App\ResourceConnection|\PHPUnit_Framework_MockObject_MockObject + * @var ResourceConnection|MockObject */ private $resourceConnectionMock; /** - * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + * @var AdapterInterface|MockObject */ private $connectionMock; /** - * @var \Magento\Authorization\Model\Rules|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Authorization\Model\Rules|MockObject */ private $ruleMock; + /** + * @inheritDoc + */ protected function setUp() { - $this->contextMock = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\Db\Context::class) + $this->contextMock = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->setMethods(['getResources']) ->getMock(); - $this->resourceConnectionMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) + $this->resourceConnectionMock = $this->getMockBuilder(ResourceConnection::class) ->disableOriginalConstructor() ->setMethods(['getConnection', 'getTableName']) ->getMock(); $this->contextMock->expects($this->once()) ->method('getResources') - ->will($this->returnValue($this->resourceConnectionMock)); + ->willReturn($this->resourceConnectionMock); - $this->connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class) + $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); $this->resourceConnectionMock->expects($this->once()) ->method('getConnection') - ->with('connection') - ->will($this->returnValue($this->connectionMock)); + ->with('default') + ->willReturn($this->connectionMock); - $this->resourceConnectionMock->expects($this->any()) - ->method('getTableName') - ->with('authorization_rule', 'connection') + $this->resourceConnectionMock->method('getTableName') + ->with('authorization_rule', 'default') ->will($this->returnArgument(0)); - $this->aclBuilderMock = $this->getMockBuilder(\Magento\Framework\Acl\Builder::class) + $this->aclBuilderMock = $this->getMockBuilder(Builder::class) ->disableOriginalConstructor() ->setMethods(['getConfigCache']) ->getMock(); - $this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->rootResourceMock = $this->getMockBuilder(\Magento\Framework\Acl\RootResource::class) + $this->rootResourceMock = $this->getMockBuilder(RootResource::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->aclDataCacheMock = $this->getMockBuilder(\Magento\Framework\Acl\Data\CacheInterface::class) + $this->aclDataCacheMock = $this->getMockBuilder(CacheInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->aclBuilderMock->expects($this->any()) - ->method('getConfigCache') - ->will($this->returnValue($this->aclDataCacheMock)); + $this->aclBuilderMock->method('getConfigCache') + ->willReturn($this->aclDataCacheMock); $this->ruleMock = $this->getMockBuilder(\Magento\Authorization\Model\Rules::class) ->disableOriginalConstructor() ->setMethods(['getRoleId']) ->getMock(); - $this->ruleMock->expects($this->any()) - ->method('getRoleId') - ->will($this->returnValue(self::TEST_ROLE_ID)); - - $this->model = new \Magento\Authorization\Model\ResourceModel\Rules( - $this->contextMock, - $this->aclBuilderMock, - $this->loggerMock, - $this->rootResourceMock, - 'connection', - $this->aclDataCacheMock + $this->ruleMock->method('getRoleId') + ->willReturn(self::TEST_ROLE_ID); + + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + Rules::class, + [ + 'context' => $this->contextMock, + 'aclBuilder' => $this->aclBuilderMock, + 'logger' => $this->loggerMock, + 'rootResource' => $this->rootResourceMock, + 'aclDataCache' => $this->aclDataCacheMock, + 'default' + ] ); } @@ -167,12 +185,12 @@ public function testSaveRelNoResources() */ public function testLocalizedExceptionOccurance() { - $exceptionPhrase = $this->getMockBuilder(\Magento\Framework\Phrase::class) + $exceptionPhrase = $this->getMockBuilder(Phrase::class) ->disableOriginalConstructor() ->setMethods(['render']) ->getMock(); - $exceptionPhrase->expects($this->any())->method('render')->will($this->returnValue('TestException')); + $exceptionPhrase->method('render')->willReturn('TestException'); $exception = new \Magento\Framework\Exception\LocalizedException($exceptionPhrase); diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index b76421e4e6f67..527bb2136b4c5 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -14,9 +14,6 @@ */ class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard { - /** - * Api URL - */ const API_URL = 'https://image-charts.com/chart'; /** @@ -190,8 +187,8 @@ public function getChartUrl($directUrl = true) $params = [ 'cht' => 'lc', 'chls' => '7', - 'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0', - 'chm' => 'B,f4d4b2,0,0,0', + 'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0', + 'chm' => 'B,f4d4b2,0,0,0', 'chco' => 'db4814', 'chxs' => '0,0,11|1,0,11', 'chma' => '15,15,15,15' @@ -237,7 +234,7 @@ public function getChartUrl($directUrl = true) case '1y': case '2y': $d = $dateStart->format('Y-m'); - $dateStart->modify('+1 month'); + $dateStart->modify('first day of next month'); break; default: $d = $dateStart->format('Y-m-d H:00'); @@ -300,20 +297,23 @@ public function getChartUrl($directUrl = true) $minvalue = min($localminvalue); // default values - $yLabels = []; $miny = 0; $maxy = 0; $yorigin = 0; + $xAxis = 'x'; + $xAxisIndex = 0; + $yAxisIndex = 1; if ($minvalue >= 0 && $maxvalue >= 0) { if ($maxvalue > 10) { - $p = pow(10, $this->_getPow((int) $maxvalue)); + $p = pow(10, $this->_getPow((int)$maxvalue)); $maxy = ceil($maxvalue / $p) * $p; - $yLabels = range($miny, $maxy, $p); + $yRange = "$yAxisIndex,$miny,$maxy,$p"; } else { $maxy = ceil($maxvalue + 1); - $yLabels = range($miny, $maxy, 1); + $yRange = "$yAxisIndex,$miny,$maxy,1"; } + $params['chxr'] = $yRange; $yorigin = 0; } @@ -341,22 +341,11 @@ public function getChartUrl($directUrl = true) $params['chd'] .= $buffer; - $valueBuffer = []; - if (count($this->_axisLabels) > 0) { $params['chxt'] = implode(',', array_keys($this->_axisLabels)); - $indexid = 0; - foreach ($this->_axisLabels as $idx => $labels) { - if ($idx == 'x') { - $this->formatAxisLabelDate((string) $idx, (string) $timezoneLocal); - $tmpstring = implode('|', $this->_axisLabels[$idx]); - $valueBuffer[] = $indexid . ":|" . $tmpstring; - } elseif ($idx == 'y') { - $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels); - } - $indexid++; - } - $params['chxl'] = implode('|', $valueBuffer); + $this->formatAxisLabelDate($xAxis, (string)$timezoneLocal); + $customAxisLabels = $xAxisIndex . ":|" . implode('|', $this->_axisLabels[$xAxis]); + $params['chxl'] = $customAxisLabels . $dataSetdelimiter; } // chart size @@ -368,7 +357,7 @@ public function getChartUrl($directUrl = true) foreach ($params as $name => $value) { $p[] = $name . '=' . urlencode($value); } - return (string) self::API_URL . '?' . implode('&', $p); + return (string)self::API_URL . '?' . implode('&', $p); } $gaData = urlencode(base64_encode(json_encode($params))); $gaHash = $this->_dashboardData->getChartDataHash($gaData); @@ -392,7 +381,7 @@ private function formatAxisLabelDate($idx, $timezoneLocal) switch ($this->getDataHelper()->getParam('period')) { case '24h': $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime( - $period->setTime((int) $period->format('H'), 0, 0), + $period->setTime((int)$period->format('H'), 0, 0), \IntlDateFormatter::NONE, \IntlDateFormatter::SHORT ); diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php index 623a75015eb2f..415ce7c4c21fc 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php @@ -9,6 +9,9 @@ use Magento\Framework\DataObject; /** + * Produce html output using the given data source. + * + * phpcs:disable Magento2.Classes.AbstractApi * Backend grid item abstract renderer * @api * @SuppressWarnings(PHPMD.NumberOfChildren) @@ -53,7 +56,7 @@ public function getColumn() * Renders grid column * * @param DataObject $row - * @return string + * @return string */ public function render(DataObject $row) { @@ -62,7 +65,7 @@ public function render(DataObject $row) $result .= $this->getColumn()->getEditOnly() ? '' : '' . $this->_getValue($row) . ''; - return $result . $this->_getInputValueElement($row) . '' ; + return $result . $this->_getInputValueElement($row) . ''; } return $this->_getValue($row); } @@ -90,6 +93,7 @@ protected function _getValue(DataObject $row) if (is_string($getter)) { return $row->{$getter}(); } elseif (is_callable($getter)) { + //phpcs:ignore Magento2.Functions.DiscouragedFunction return call_user_func($getter, $row); } return ''; diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml similarity index 72% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml index 7e1dfe4cf381b..0320862b99e63 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminLoginActionGroup.xml @@ -8,18 +8,20 @@ - + Login to Backend Admin using provided User Data. PLEASE NOTE: This Action Group does NOT validate that you are Logged In. - + + - - + + + diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminSetStoreInformationConfigurationActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminSetStoreInformationConfigurationActionGroup.xml new file mode 100644 index 0000000000000..9de4b684f6f5c --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminSetStoreInformationConfigurationActionGroup.xml @@ -0,0 +1,36 @@ + + + + + + + Set Store Information configurations + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml deleted file mode 100644 index 7068478bb4790..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - Login to Backend Admin using ENV Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In. - - - - - - - - diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml deleted file mode 100644 index 995a5e7130e0a..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginAdminWithCredentialsActionGroup.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - Login to Backend Admin using provided Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In. - - - - - - - - - - - - - diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LogoutActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LogoutActionGroup.xml deleted file mode 100644 index 4c265d08dd041..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LogoutActionGroup.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - Logout of the Backend Admin. PLEASE NOTE: This Action Group does NOT validate that you are Logged Out. - - - - - diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml new file mode 100644 index 0000000000000..d2f4496c8cd4e --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + Login to Backend Admin using provided User Data. PLEASE NOTE: This Action Group does NOT validate that you are Logged In. + + + + + + + + + + + + + + + + + Login to Backend Admin using provided Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In. + + + + + + + + + + + + + diff --git a/app/code/Magento/Backend/Test/Mftf/Data/AdminGeneralStoreInfomationConfigData.xml b/app/code/Magento/Backend/Test/Mftf/Data/AdminGeneralStoreInfomationConfigData.xml index a8db2f94d69ab..2c50bc0fc75f4 100644 --- a/app/code/Magento/Backend/Test/Mftf/Data/AdminGeneralStoreInfomationConfigData.xml +++ b/app/code/Magento/Backend/Test/Mftf/Data/AdminGeneralStoreInfomationConfigData.xml @@ -30,4 +30,11 @@ general/store_information/street_line2 + + general/store_information/region_id + + + general/store_information/hours + 8AM-8PM + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminAttributeTextSwatchesCanBeFiledTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminAttributeTextSwatchesCanBeFiledTest.xml index 2c061e54f5509..32201e03f92ec 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminAttributeTextSwatchesCanBeFiledTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminAttributeTextSwatchesCanBeFiledTest.xml @@ -58,7 +58,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminContentScheduleNavigateMenuTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminContentScheduleNavigateMenuTest.xml index bead59653eee8..091e441559d78 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminContentScheduleNavigateMenuTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminContentScheduleNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardNavigateMenuTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardNavigateMenuTest.xml index 6434d74b28754..60118202dbef2 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardNavigateMenuTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml index 3ba965f746722..e82d54280d4e1 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminDashboardWithChartsChart.xml @@ -37,7 +37,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminExpireCustomerSessionTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminExpireCustomerSessionTest.xml index 88646401e3a99..d932da6ec0fad 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminExpireCustomerSessionTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminExpireCustomerSessionTest.xml @@ -24,7 +24,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterChangeCookieDomainTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterChangeCookieDomainTest.xml index 93d411c8827ed..f75f3b2e3f15e 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterChangeCookieDomainTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterChangeCookieDomainTest.xml @@ -29,6 +29,6 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml index 5550e3b317b0d..0aa31bb21b6f7 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml @@ -26,7 +26,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml index 960e77db7194f..566328e075600 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml @@ -22,6 +22,6 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginWithRestrictPermissionTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginWithRestrictPermissionTest.xml index e664a4a5f3e2f..a9706d902ff34 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginWithRestrictPermissionTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginWithRestrictPermissionTest.xml @@ -39,7 +39,7 @@ - + @@ -52,7 +52,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminMenuNavigationWithSecretKeysTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminMenuNavigationWithSecretKeysTest.xml index c9a3b8089cc1d..db81a7829160d 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminMenuNavigationWithSecretKeysTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminMenuNavigationWithSecretKeysTest.xml @@ -26,7 +26,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresAllStoresNavigateMenuTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresAllStoresNavigateMenuTest.xml index 7758b387e393b..0ff1e817ac0ea 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresAllStoresNavigateMenuTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresAllStoresNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresConfigurationNavigateMenuTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresConfigurationNavigateMenuTest.xml index a54269b186ba0..94bf5c6b8993a 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresConfigurationNavigateMenuTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminStoresConfigurationNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminSystemCacheManagementNavigateMenuTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminSystemCacheManagementNavigateMenuTest.xml index 516631c1bd166..3aae643ccc36b 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminSystemCacheManagementNavigateMenuTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminSystemCacheManagementNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 3a2b3554cc4a0..1e8ec226d6b88 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -115,7 +115,7 @@ Magento\Config\Model\Config\Source\Yesno - + 1 @@ -123,7 +123,7 @@ Magento\Config\Model\Config\Source\Yesno Use URL parameter to enable template path hints for Storefront - + 1 diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 51fe8bfe542a2..53f7fe90cbbe5 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -461,3 +461,5 @@ Pagination,Pagination "Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used.","Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used." "Anchor Text for Next","Anchor Text for Next" "Theme Name","Theme Name" +"Use URL parameter to enable template path hints for Storefront","Use URL parameter to enable template path hints for Storefront" +"Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]","Add the following parameter to the URL to show template hints ?templatehints=[parameter_value]" diff --git a/app/code/Magento/Backup/Test/Mftf/Test/AdminCreateAndDeleteBackupsTest.xml b/app/code/Magento/Backup/Test/Mftf/Test/AdminCreateAndDeleteBackupsTest.xml index 778c6d5112b6a..383c1122ee07f 100644 --- a/app/code/Magento/Backup/Test/Mftf/Test/AdminCreateAndDeleteBackupsTest.xml +++ b/app/code/Magento/Backup/Test/Mftf/Test/AdminCreateAndDeleteBackupsTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php b/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php index de439aad2defd..d35906c929b2a 100644 --- a/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php +++ b/app/code/Magento/Braintree/Gateway/Command/CaptureStrategyCommand.php @@ -21,7 +21,8 @@ use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; /** - * Class CaptureStrategyCommand + * Braintree capture implementation. + * * @SuppressWarnings(PHPMD) */ class CaptureStrategyCommand implements CommandInterface @@ -84,7 +85,7 @@ class CaptureStrategyCommand implements CommandInterface * @param FilterBuilder $filterBuilder * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param SubjectReader $subjectReader - * @param BraintreeAdapterFactory $braintreeAdapterFactory, + * @param BraintreeAdapterFactory $braintreeAdapterFactory * @param BraintreeSearchAdapter $braintreeSearchAdapter */ public function __construct( @@ -112,9 +113,9 @@ public function execute(array $commandSubject) { /** @var \Magento\Payment\Gateway\Data\PaymentDataObjectInterface $paymentDO */ $paymentDO = $this->subjectReader->readPayment($commandSubject); - $command = $this->getCommand($paymentDO); - $this->commandPool->get($command)->execute($commandSubject); + + return $this->commandPool->get($command)->execute($commandSubject); } /** @@ -128,11 +129,8 @@ private function getCommand(PaymentDataObjectInterface $paymentDO) $payment = $paymentDO->getPayment(); ContextHelper::assertOrderPayment($payment); - // if auth transaction does not exist then execute authorize&capture command + // if capture transaction does not exist then execute capture command $existsCapture = $this->isExistsCaptureTransaction($payment); - if (!$payment->getAuthorizationTransaction() && !$existsCapture) { - return self::SALE; - } // do capture for authorization transaction if (!$existsCapture && !$this->isExpiredAuthorization($payment, $paymentDO->getOrder())) { diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml b/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml index 16c8c93e94cbe..c45a8aece5ffc 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/CreateAnAdminOrderUsingBraintreePaymentTest1.xml @@ -53,7 +53,7 @@ - + diff --git a/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml b/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml index 371b59418e4a9..d2b0479f2bba6 100644 --- a/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml +++ b/app/code/Magento/Braintree/Test/Mftf/Test/CretateAdminOrderWithOnlinePaymentIncludingTaxAndDiscount.xml @@ -70,7 +70,7 @@ - + diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php index 845a02930d709..969894a20f9de 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php @@ -24,8 +24,6 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** - * Tests \Magento\Braintree\Gateway\Command\CaptureStrategyCommand. - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase @@ -38,42 +36,42 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase /** * @var CommandPoolInterface|MockObject */ - private $commandPoolMock; + private $commandPool; /** * @var TransactionRepositoryInterface|MockObject */ - private $transactionRepositoryMock; + private $transactionRepository; /** * @var FilterBuilder|MockObject */ - private $filterBuilderMock; + private $filterBuilder; /** * @var SearchCriteriaBuilder|MockObject */ - private $searchCriteriaBuilderMock; + private $searchCriteriaBuilder; /** * @var Payment|MockObject */ - private $paymentMock; + private $payment; /** * @var GatewayCommand|MockObject */ - private $commandMock; + private $command; /** * @var SubjectReader|MockObject */ - private $subjectReaderMock; + private $subjectReader; /** * @var BraintreeAdapter|MockObject */ - private $braintreeAdapterMock; + private $braintreeAdapter; /** * @var BraintreeSearchAdapter @@ -82,12 +80,12 @@ class CaptureStrategyCommandTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->commandPoolMock = $this->getMockBuilder(CommandPoolInterface::class) + $this->commandPool = $this->getMockBuilder(CommandPoolInterface::class) ->disableOriginalConstructor() ->setMethods(['get', '__wakeup']) ->getMock(); - $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class) + $this->subjectReader = $this->getMockBuilder(SubjectReader::class) ->disableOriginalConstructor() ->getMock(); @@ -96,106 +94,60 @@ protected function setUp() $this->initFilterBuilderMock(); $this->initSearchCriteriaBuilderMock(); - $this->braintreeAdapterMock = $this->getMockBuilder(BraintreeAdapter::class) + $this->braintreeAdapter = $this->getMockBuilder(BraintreeAdapter::class) ->disableOriginalConstructor() ->getMock(); - /** @var BraintreeAdapterFactory|MockObject $adapterFactoryMock */ - $adapterFactoryMock = $this->getMockBuilder(BraintreeAdapterFactory::class) + /** @var BraintreeAdapterFactory|MockObject $adapterFactory */ + $adapterFactory = $this->getMockBuilder(BraintreeAdapterFactory::class) ->disableOriginalConstructor() ->getMock(); - $adapterFactoryMock->expects(self::any()) - ->method('create') - ->willReturn($this->braintreeAdapterMock); + $adapterFactory->method('create') + ->willReturn($this->braintreeAdapter); $this->braintreeSearchAdapter = new BraintreeSearchAdapter(); $this->strategyCommand = new CaptureStrategyCommand( - $this->commandPoolMock, - $this->transactionRepositoryMock, - $this->filterBuilderMock, - $this->searchCriteriaBuilderMock, - $this->subjectReaderMock, - $adapterFactoryMock, + $this->commandPool, + $this->transactionRepository, + $this->filterBuilder, + $this->searchCriteriaBuilder, + $this->subjectReader, + $adapterFactory, $this->braintreeSearchAdapter ); } - /** - * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute - */ - public function testSaleExecute() - { - $paymentData = $this->getPaymentDataObjectMock(); - $subject['payment'] = $paymentData; - - $this->subjectReaderMock->expects(self::once()) - ->method('readPayment') - ->with($subject) - ->willReturn($paymentData); - - $this->paymentMock->expects(static::once()) - ->method('getAuthorizationTransaction') - ->willReturn(false); - - $this->paymentMock->expects(static::once()) - ->method('getId') - ->willReturn(1); - - $this->buildSearchCriteria(); - - $this->transactionRepositoryMock->expects(static::once()) - ->method('getTotalCount') - ->willReturn(0); - - $this->commandPoolMock->expects(static::once()) - ->method('get') - ->with(CaptureStrategyCommand::SALE) - ->willReturn($this->commandMock); - - $this->strategyCommand->execute($subject); - } - - /** - * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute - */ public function testCaptureExecute() { $paymentData = $this->getPaymentDataObjectMock(); $subject['payment'] = $paymentData; $lastTransId = 'txnds'; - $this->subjectReaderMock->expects(self::once()) - ->method('readPayment') + $this->subjectReader->method('readPayment') ->with($subject) ->willReturn($paymentData); - $this->paymentMock->expects(static::once()) - ->method('getAuthorizationTransaction') + $this->payment->method('getAuthorizationTransaction') ->willReturn(true); - $this->paymentMock->expects(static::once()) - ->method('getLastTransId') + $this->payment->method('getLastTransId') ->willReturn($lastTransId); - $this->paymentMock->expects(static::once()) - ->method('getId') + $this->payment->method('getId') ->willReturn(1); $this->buildSearchCriteria(); - $this->transactionRepositoryMock->expects(static::once()) - ->method('getTotalCount') + $this->transactionRepository->method('getTotalCount') ->willReturn(0); // authorization transaction was not expired $collection = $this->getNotExpiredExpectedCollection($lastTransId); - $collection->expects(static::once()) - ->method('maximumCount') + $collection->method('maximumCount') ->willReturn(0); - $this->commandPoolMock->expects(static::once()) - ->method('get') + $this->commandPool->method('get') ->with(CaptureStrategyCommand::CAPTURE) - ->willReturn($this->commandMock); + ->willReturn($this->command); $this->strategyCommand->execute($subject); } @@ -215,10 +167,9 @@ private function getNotExpiredExpectedCollection($lastTransactionId) ->disableOriginalConstructor() ->getMock(); - $this->braintreeAdapterMock->expects(static::once()) - ->method('search') + $this->braintreeAdapter->method('search') ->with( - static::callback( + self::callback( function (array $filters) use ($isExpectations) { foreach ($filters as $filter) { /** @var IsNode $filter */ @@ -240,82 +191,64 @@ function (array $filters) use ($isExpectations) { return $collection; } - /** - * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute - */ public function testExpiredAuthorizationPerformVaultCaptureExecute() { $paymentData = $this->getPaymentDataObjectMock(); $subject['payment'] = $paymentData; $lastTransId = 'txnds'; - $this->subjectReaderMock->expects(self::once()) - ->method('readPayment') + $this->subjectReader->method('readPayment') ->with($subject) ->willReturn($paymentData); - $this->paymentMock->expects(static::once()) - ->method('getAuthorizationTransaction') + $this->payment->method('getAuthorizationTransaction') ->willReturn(true); - $this->paymentMock->expects(static::once()) - ->method('getLastTransId') + $this->payment->method('getLastTransId') ->willReturn($lastTransId); - $this->paymentMock->expects(static::once()) - ->method('getId') + $this->payment->method('getId') ->willReturn(1); $this->buildSearchCriteria(); - $this->transactionRepositoryMock->expects(static::once()) - ->method('getTotalCount') + $this->transactionRepository->method('getTotalCount') ->willReturn(0); // authorization transaction was expired $collection = $this->getNotExpiredExpectedCollection($lastTransId); - $collection->expects(static::once()) - ->method('maximumCount') + $collection->method('maximumCount') ->willReturn(1); - $this->commandPoolMock->expects(static::once()) - ->method('get') + $this->commandPool->method('get') ->with(CaptureStrategyCommand::VAULT_CAPTURE) - ->willReturn($this->commandMock); + ->willReturn($this->command); $this->strategyCommand->execute($subject); } - /** - * @covers \Magento\Braintree\Gateway\Command\CaptureStrategyCommand::execute - */ public function testVaultCaptureExecute() { $paymentData = $this->getPaymentDataObjectMock(); $subject['payment'] = $paymentData; - $this->subjectReaderMock->expects(self::once()) - ->method('readPayment') + $this->subjectReader->method('readPayment') ->with($subject) ->willReturn($paymentData); - $this->paymentMock->expects(static::once()) - ->method('getAuthorizationTransaction') + $this->payment->method('getAuthorizationTransaction') ->willReturn(true); - $this->paymentMock->expects(static::once()) - ->method('getId') + $this->payment->method('getId') ->willReturn(1); $this->buildSearchCriteria(); - $this->transactionRepositoryMock->expects(static::once()) - ->method('getTotalCount') + $this->transactionRepository->method('getTotalCount') ->willReturn(1); - $this->commandPoolMock->expects(static::once()) - ->method('get') + $this->commandPool->method('get') ->with(CaptureStrategyCommand::VAULT_CAPTURE) - ->willReturn($this->commandMock); + ->willReturn($this->command); $this->strategyCommand->execute($subject); } @@ -326,7 +259,7 @@ public function testVaultCaptureExecute() */ private function getPaymentDataObjectMock() { - $this->paymentMock = $this->getMockBuilder(Payment::class) + $this->payment = $this->getMockBuilder(Payment::class) ->disableOriginalConstructor() ->getMock(); @@ -335,16 +268,15 @@ private function getPaymentDataObjectMock() ->disableOriginalConstructor() ->getMock(); - $mock->expects(static::once()) - ->method('getPayment') - ->willReturn($this->paymentMock); + $mock->method('getPayment') + ->willReturn($this->payment); - $orderMock = $this->getMockBuilder(OrderAdapterInterface::class) + $order = $this->getMockBuilder(OrderAdapterInterface::class) ->disableOriginalConstructor() ->getMock(); $mock->method('getOrder') - ->willReturn($orderMock); + ->willReturn($order); return $mock; } @@ -354,13 +286,12 @@ private function getPaymentDataObjectMock() */ private function initCommandMock() { - $this->commandMock = $this->getMockBuilder(GatewayCommand::class) + $this->command = $this->getMockBuilder(GatewayCommand::class) ->disableOriginalConstructor() ->setMethods(['execute']) ->getMock(); - $this->commandMock->expects(static::once()) - ->method('execute') + $this->command->method('execute') ->willReturn([]); } @@ -369,7 +300,7 @@ private function initCommandMock() */ private function initFilterBuilderMock() { - $this->filterBuilderMock = $this->getMockBuilder(FilterBuilder::class) + $this->filterBuilder = $this->getMockBuilder(FilterBuilder::class) ->disableOriginalConstructor() ->setMethods(['setField', 'setValue', 'create', '__wakeup']) ->getMock(); @@ -380,23 +311,21 @@ private function initFilterBuilderMock() */ private function buildSearchCriteria() { - $this->filterBuilderMock->expects(static::exactly(2)) + $this->filterBuilder->expects(self::exactly(2)) ->method('setField') ->willReturnSelf(); - $this->filterBuilderMock->expects(static::exactly(2)) + $this->filterBuilder->expects(self::exactly(2)) ->method('setValue') ->willReturnSelf(); $searchCriteria = new SearchCriteria(); - $this->searchCriteriaBuilderMock->expects(static::exactly(2)) + $this->searchCriteriaBuilder->expects(self::exactly(2)) ->method('addFilters') ->willReturnSelf(); - $this->searchCriteriaBuilderMock->expects(static::once()) - ->method('create') + $this->searchCriteriaBuilder->method('create') ->willReturn($searchCriteria); - $this->transactionRepositoryMock->expects(static::once()) - ->method('getList') + $this->transactionRepository->method('getList') ->with($searchCriteria) ->willReturnSelf(); } @@ -406,7 +335,7 @@ private function buildSearchCriteria() */ private function initSearchCriteriaBuilderMock() { - $this->searchCriteriaBuilderMock = $this->getMockBuilder(SearchCriteriaBuilder::class) + $this->searchCriteriaBuilder = $this->getMockBuilder(SearchCriteriaBuilder::class) ->disableOriginalConstructor() ->setMethods(['addFilters', 'create', '__wakeup']) ->getMock(); @@ -417,7 +346,7 @@ private function initSearchCriteriaBuilderMock() */ private function initTransactionRepositoryMock() { - $this->transactionRepositoryMock = $this->getMockBuilder(TransactionRepositoryInterface::class) + $this->transactionRepository = $this->getMockBuilder(TransactionRepositoryInterface::class) ->disableOriginalConstructor() ->setMethods(['getList', 'getTotalCount', 'delete', 'get', 'save', 'create', '__wakeup']) ->getMock(); diff --git a/app/code/Magento/Braintree/etc/config.xml b/app/code/Magento/Braintree/etc/config.xml index 522d32302168e..b681100dc4dd0 100644 --- a/app/code/Magento/Braintree/etc/config.xml +++ b/app/code/Magento/Braintree/etc/config.xml @@ -15,6 +15,7 @@ 0 1 1 + 1 1 1 1 diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js index 43aec27508ce9..b66725c063414 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/3d-secure.js @@ -117,7 +117,7 @@ define([ options.bin = context.paymentPayload.details.bin; } - if (shippingAddress) { + if (shippingAddress && this.isValidShippingAddress(shippingAddress)) { options.additionalInformation = { shippingGivenName: shippingAddress.firstname, shippingSurname: shippingAddress.lastname, @@ -206,6 +206,25 @@ define([ } return false; + }, + + /** + * Validate shipping address + * + * @param {Object} shippingAddress + * @return {Boolean} + */ + isValidShippingAddress: function (shippingAddress) { + var isValid = false; + + // check that required fields are not empty + if (shippingAddress.firstname && shippingAddress.lastname && shippingAddress.telephone && + shippingAddress.street && shippingAddress.city && shippingAddress.regionCode && + shippingAddress.postcode && shippingAddress.countryId) { + isValid = true; + } + + return isValid; } }; }); diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js index afe22475981ec..21809f186d252 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js @@ -91,7 +91,7 @@ define( }) .then(function (hostedFieldsInstance) { self.hostedFieldsInstance = hostedFieldsInstance; - self.isPlaceOrderActionAllowed(true); + self.isPlaceOrderActionAllowed(false); self.initFormValidationEvents(hostedFieldsInstance); return self.hostedFieldsInstance; diff --git a/app/code/Magento/Bundle/Helper/Data.php b/app/code/Magento/Bundle/Helper/Data.php index dbd4a6a039c27..944876cbdad72 100644 --- a/app/code/Magento/Bundle/Helper/Data.php +++ b/app/code/Magento/Bundle/Helper/Data.php @@ -38,6 +38,6 @@ public function getAllowedSelectionTypes() { $configData = $this->config->getType(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE); - return isset($configData['allowed_selection_types']) ? $configData['allowed_selection_types'] : []; + return $configData['allowed_selection_types'] ?? []; } } diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleItemsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleItemsTest.xml index bf428440a24eb..2b6b139520f97 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleItemsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleItemsTest.xml @@ -36,7 +36,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml index b2d3c376d9b5a..1498e52850fd5 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAddBundleProductToCartFromWishListPageTest.xml @@ -60,7 +60,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAssociateBundleProductToWebsitesTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAssociateBundleProductToWebsitesTest.xml index b58637cf2e81d..823ad303c5455 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminAssociateBundleProductToWebsitesTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminAssociateBundleProductToWebsitesTest.xml @@ -82,7 +82,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml index a80d5f040f825..b143bd63280ea 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml @@ -38,7 +38,7 @@ - + @@ -180,7 +180,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleDynamicProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleDynamicProductTest.xml index 51821b136ba26..a3e9a8af40a34 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleDynamicProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleDynamicProductTest.xml @@ -29,7 +29,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleFixedProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleFixedProductTest.xml index dcd53fff6f6dd..0c26fb1775bff 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleFixedProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminDeleteBundleFixedProductTest.xml @@ -26,7 +26,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml index 632ba194cf8de..fbb9dda50f0d9 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml @@ -70,6 +70,8 @@ + + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminProductBundleCreationTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminProductBundleCreationTest.xml index 78bc85da6f69b..7d82c6e5b43ad 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminProductBundleCreationTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminProductBundleCreationTest.xml @@ -33,7 +33,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml index 994a10ae02692..173319affe53b 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminShouldBeAbleToMassUpdateAttributesForBundleProductsTest.xml @@ -43,7 +43,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/BundleProductFixedPricingTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/BundleProductFixedPricingTest.xml index 2b36458caa182..80920c2e6d851 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/BundleProductFixedPricingTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/BundleProductFixedPricingTest.xml @@ -35,7 +35,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/EnableDisableBundleProductStatusTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/EnableDisableBundleProductStatusTest.xml index f73818a86a025..f1124e5446b58 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/EnableDisableBundleProductStatusTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/EnableDisableBundleProductStatusTest.xml @@ -31,7 +31,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleOptionsToCartTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleOptionsToCartTest.xml index 7ad97a8991349..38926ccfbb7d6 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleOptionsToCartTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleOptionsToCartTest.xml @@ -48,7 +48,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleProductWithZeroPriceToShoppingCartTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleProductWithZeroPriceToShoppingCartTest.xml index 64b786ac4ed7c..7ff88c49f0bc7 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleProductWithZeroPriceToShoppingCartTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAddBundleProductWithZeroPriceToShoppingCartTest.xml @@ -48,7 +48,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductDetailsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductDetailsTest.xml index cc0064e87c3c1..b174ee2ee3c70 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductDetailsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductDetailsTest.xml @@ -34,7 +34,7 @@ - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml index 0487668c10094..4bb54436e8729 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -42,10 +42,9 @@ - + - - + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml index dc8cb24246567..613187a4c3856 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml @@ -22,6 +22,8 @@ + + @@ -89,6 +91,10 @@ + + + + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml index 9dbd6e26bddc4..3a40a1b7eeb71 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml @@ -65,6 +65,8 @@ + + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontSortBundleProductsByPriceTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontSortBundleProductsByPriceTest.xml index 8bf0de7530e64..eaaa9c4356617 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontSortBundleProductsByPriceTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontSortBundleProductsByPriceTest.xml @@ -109,6 +109,9 @@ + + + diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontVerifyDynamicBundleProductPricesForCombinationOfOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontVerifyDynamicBundleProductPricesForCombinationOfOptionsTest.xml index c78796d2fd8b4..896c4f8f25fec 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontVerifyDynamicBundleProductPricesForCombinationOfOptionsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontVerifyDynamicBundleProductPricesForCombinationOfOptionsTest.xml @@ -192,7 +192,7 @@ - + diff --git a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php index 7608d6e9e4d97..c8e2384fcb99c 100644 --- a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php +++ b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php @@ -78,11 +78,7 @@ public function addParentFilterData(int $parentId, int $parentEntityId, string $ public function getOptionsByParentId(int $parentId) : array { $options = $this->fetch(); - if (!isset($options[$parentId])) { - return []; - } - - return $options[$parentId]; + return $options[$parentId] ?? []; } /** @@ -115,7 +111,7 @@ private function fetch() : array $this->extensionAttributesJoinProcessor->process($optionsCollection); if (empty($optionsCollection->getData())) { - return null; + return []; } /** @var \Magento\Bundle\Model\Option $option */ diff --git a/app/code/Magento/Captcha/Observer/CheckContactUsFormObserver.php b/app/code/Magento/Captcha/Observer/CheckContactUsFormObserver.php index 8c1da0e1ef104..2d0a6479bbcd6 100644 --- a/app/code/Magento/Captcha/Observer/CheckContactUsFormObserver.php +++ b/app/code/Magento/Captcha/Observer/CheckContactUsFormObserver.php @@ -3,34 +3,41 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Captcha\Observer; +use Magento\Captcha\Helper\Data; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\ActionFlag; +use Magento\Framework\App\Response\RedirectInterface; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\App\Request\DataPersistorInterface; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\Message\ManagerInterface; /** - * Class CheckContactUsFormObserver + * Check captcha on contact us form submit observer. */ class CheckContactUsFormObserver implements ObserverInterface { /** - * @var \Magento\Captcha\Helper\Data + * @var Data */ protected $_helper; /** - * @var \Magento\Framework\App\ActionFlag + * @var ActionFlag */ protected $_actionFlag; /** - * @var \Magento\Framework\Message\ManagerInterface + * @var ManagerInterface */ protected $messageManager; /** - * @var \Magento\Framework\App\Response\RedirectInterface + * @var RedirectInterface */ protected $redirect; @@ -45,60 +52,48 @@ class CheckContactUsFormObserver implements ObserverInterface private $dataPersistor; /** - * @param \Magento\Captcha\Helper\Data $helper - * @param \Magento\Framework\App\ActionFlag $actionFlag - * @param \Magento\Framework\Message\ManagerInterface $messageManager - * @param \Magento\Framework\App\Response\RedirectInterface $redirect + * @param Data $helper + * @param ActionFlag $actionFlag + * @param ManagerInterface $messageManager + * @param RedirectInterface $redirect * @param CaptchaStringResolver $captchaStringResolver + * @param DataPersistorInterface $dataPersistor */ public function __construct( - \Magento\Captcha\Helper\Data $helper, - \Magento\Framework\App\ActionFlag $actionFlag, - \Magento\Framework\Message\ManagerInterface $messageManager, - \Magento\Framework\App\Response\RedirectInterface $redirect, - CaptchaStringResolver $captchaStringResolver + Data $helper, + ActionFlag $actionFlag, + ManagerInterface $messageManager, + RedirectInterface $redirect, + CaptchaStringResolver $captchaStringResolver, + DataPersistorInterface $dataPersistor ) { $this->_helper = $helper; $this->_actionFlag = $actionFlag; $this->messageManager = $messageManager; $this->redirect = $redirect; $this->captchaStringResolver = $captchaStringResolver; + $this->dataPersistor = $dataPersistor; } /** * Check CAPTCHA on Contact Us page * - * @param \Magento\Framework\Event\Observer $observer + * @param Observer $observer * @return void */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { $formId = 'contact_us'; $captcha = $this->_helper->getCaptcha($formId); if ($captcha->isRequired()) { - /** @var \Magento\Framework\App\Action\Action $controller */ + /** @var Action $controller */ $controller = $observer->getControllerAction(); if (!$captcha->isCorrect($this->captchaStringResolver->resolve($controller->getRequest(), $formId))) { $this->messageManager->addErrorMessage(__('Incorrect CAPTCHA.')); - $this->getDataPersistor()->set($formId, $controller->getRequest()->getPostValue()); - $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true); + $this->dataPersistor->set($formId, $controller->getRequest()->getPostValue()); + $this->_actionFlag->set('', Action::FLAG_NO_DISPATCH, true); $this->redirect->redirect($controller->getResponse(), 'contact/index/index'); } } } - - /** - * Get Data Persistor - * - * @return DataPersistorInterface - */ - private function getDataPersistor() - { - if ($this->dataPersistor === null) { - $this->dataPersistor = ObjectManager::getInstance() - ->get(DataPersistorInterface::class); - } - - return $this->dataPersistor; - } } diff --git a/app/code/Magento/Captcha/Observer/ResetAttemptForBackendObserver.php b/app/code/Magento/Captcha/Observer/ResetAttemptForBackendObserver.php index 376bffbd9a6a5..165aef3d7f587 100644 --- a/app/code/Magento/Captcha/Observer/ResetAttemptForBackendObserver.php +++ b/app/code/Magento/Captcha/Observer/ResetAttemptForBackendObserver.php @@ -5,20 +5,27 @@ */ namespace Magento\Captcha\Observer; +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Exception\LocalizedException; +/** + * Reset captcha attempts for Backend + */ class ResetAttemptForBackendObserver implements ObserverInterface { /** - * @var \Magento\Captcha\Model\ResourceModel\LogFactory + * @var LogFactory */ public $resLogFactory; /** - * @param \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory + * @param LogFactory $resLogFactory */ public function __construct( - \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory + LogFactory $resLogFactory ) { $this->resLogFactory = $resLogFactory; } @@ -26,10 +33,11 @@ public function __construct( /** * Reset Attempts For Backend * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Captcha\Observer\ResetAttemptForBackendObserver + * @param Observer $observer + * @return Log + * @throws LocalizedException */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { return $this->resLogFactory->create()->deleteUserAttempts($observer->getUser()->getUsername()); } diff --git a/app/code/Magento/Captcha/Observer/ResetAttemptForFrontendObserver.php b/app/code/Magento/Captcha/Observer/ResetAttemptForFrontendObserver.php index dedb57ad52581..e65793cd3508e 100644 --- a/app/code/Magento/Captcha/Observer/ResetAttemptForFrontendObserver.php +++ b/app/code/Magento/Captcha/Observer/ResetAttemptForFrontendObserver.php @@ -5,20 +5,28 @@ */ namespace Magento\Captcha\Observer; +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Customer\Model\Customer; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Exception\LocalizedException; +/** + * Reset captcha attempts for Frontend + */ class ResetAttemptForFrontendObserver implements ObserverInterface { /** - * @var \Magento\Captcha\Model\ResourceModel\LogFactory + * @var LogFactory */ public $resLogFactory; /** - * @param \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory + * @param LogFactory $resLogFactory */ public function __construct( - \Magento\Captcha\Model\ResourceModel\LogFactory $resLogFactory + LogFactory $resLogFactory ) { $this->resLogFactory = $resLogFactory; } @@ -26,12 +34,13 @@ public function __construct( /** * Reset Attempts For Frontend * - * @param \Magento\Framework\Event\Observer $observer - * @return \Magento\Captcha\Observer\ResetAttemptForFrontendObserver + * @param Observer $observer + * @return Log + * @throws LocalizedException */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { - /** @var \Magento\Customer\Model\Customer $model */ + /** @var Customer $model */ $model = $observer->getModel(); return $this->resLogFactory->create()->deleteUserAttempts($model->getEmail()); diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckContactUsFormObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckContactUsFormObserverTest.php index 83bfb2910f9f8..6bb21e9432d70 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/CheckContactUsFormObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckContactUsFormObserverTest.php @@ -5,94 +5,108 @@ */ namespace Magento\Captcha\Test\Unit\Observer; +use Magento\Captcha\Helper\Data; +use Magento\Captcha\Model\DefaultModel; +use Magento\Captcha\Observer\CaptchaStringResolver; +use Magento\Captcha\Observer\CheckContactUsFormObserver; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\ActionFlag; +use Magento\Framework\App\Request\DataPersistorInterface; +use Magento\Framework\App\Request\Http; +use Magento\Framework\App\Response\RedirectInterface; +use Magento\Framework\Event\Observer; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Session\SessionManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + /** + * Test class for \Magento\Captcha\Observer\CheckContactUsFormObserver + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CheckContactUsFormObserverTest extends \PHPUnit\Framework\TestCase +class CheckContactUsFormObserverTest extends TestCase { /** - * @var \Magento\Captcha\Observer\CheckContactUsFormObserver + * @var ObjectManager */ - protected $checkContactUsFormObserver; + private $objectManagerHelper; /** - * @var \Magento\Captcha\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var CheckContactUsFormObserver */ - protected $helperMock; + private $checkContactUsFormObserver; /** - * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject + * @var Data|MockObject */ - protected $actionFlagMock; + private $helperMock; - /* - * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + /** + * @var ActionFlag|MockObject */ - protected $messageManagerMock; + private $actionFlagMock; /** - * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ManagerInterface|MockObject */ - protected $redirectMock; + private $messageManagerMock; /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var RedirectInterface|MockObject */ - protected $objectManagerHelper; + private $redirectMock; /** - * @var \Magento\Captcha\Observer\CaptchaStringResolver|\PHPUnit_Framework_MockObject_MockObject + * @var CaptchaStringResolver|MockObject */ - protected $captchaStringResolverMock; + private $captchaStringResolverMock; /** - * @var \Magento\Framework\Session\SessionManager|\PHPUnit_Framework_MockObject_MockObject + * @var DataPersistorInterface|MockObject */ - protected $sessionMock; + private $dataPersistorMock; /** - * @var \Magento\Captcha\Model\DefaultModel|\PHPUnit_Framework_MockObject_MockObject + * @var SessionManager|MockObject */ - protected $captchaMock; + private $sessionMock; /** - * @var \Magento\Framework\App\Request\DataPersistorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var DefaultModel|MockObject */ - protected $dataPersistorMock; + private $captchaMock; protected function setUp() { - $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManagerHelper = new ObjectManager($this); + + $this->helperMock = $this->createMock(Data::class); + $this->actionFlagMock = $this->createMock(ActionFlag::class); + $this->messageManagerMock = $this->createMock(ManagerInterface::class); + $this->redirectMock = $this->createMock(RedirectInterface::class); + $this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class); + $this->dataPersistorMock = $this->getMockBuilder(DataPersistorInterface::class) + ->getMockForAbstractClass(); - $this->helperMock = $this->createMock(\Magento\Captcha\Helper\Data::class); - $this->actionFlagMock = $this->createMock(\Magento\Framework\App\ActionFlag::class); - $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\ManagerInterface::class); - $this->redirectMock = $this->createMock(\Magento\Framework\App\Response\RedirectInterface::class); - $this->captchaStringResolverMock = $this->createMock(\Magento\Captcha\Observer\CaptchaStringResolver::class); $this->sessionMock = $this->createPartialMock( - \Magento\Framework\Session\SessionManager::class, + SessionManager::class, ['addErrorMessage'] ); - $this->dataPersistorMock = $this->getMockBuilder(\Magento\Framework\App\Request\DataPersistorInterface::class) - ->getMockForAbstractClass(); + $this->captchaMock = $this->createMock(DefaultModel::class); $this->checkContactUsFormObserver = $this->objectManagerHelper->getObject( - \Magento\Captcha\Observer\CheckContactUsFormObserver::class, + CheckContactUsFormObserver::class, [ 'helper' => $this->helperMock, 'actionFlag' => $this->actionFlagMock, 'messageManager' => $this->messageManagerMock, 'redirect' => $this->redirectMock, - 'captchaStringResolver' => $this->captchaStringResolverMock + 'captchaStringResolver' => $this->captchaStringResolverMock, + 'dataPersistor' => $this->dataPersistorMock ] ); - $this->objectManagerHelper->setBackwardCompatibleProperty( - $this->checkContactUsFormObserver, - 'dataPersistor', - $this->dataPersistorMock - ); - - $this->captchaMock = $this->createMock(\Magento\Captcha\Model\DefaultModel::class); } public function testCheckContactUsFormWhenCaptchaIsRequiredAndValid() @@ -100,14 +114,13 @@ public function testCheckContactUsFormWhenCaptchaIsRequiredAndValid() $formId = 'contact_us'; $captchaValue = 'some-value'; - $controller = $this->createMock(\Magento\Framework\App\Action\Action::class); - $request = $this->createMock(\Magento\Framework\App\Request\Http::class); - $request->expects($this->any()) - ->method('getPost') - ->with(\Magento\Captcha\Helper\Data::INPUT_NAME_FIELD_VALUE, null) + $controller = $this->createMock(Action::class); + $request = $this->createMock(Http::class); + $request->method('getPost') + ->with(Data::INPUT_NAME_FIELD_VALUE, null) ->willReturn([$formId => $captchaValue]); - $controller->expects($this->any())->method('getRequest')->willReturn($request); - $this->captchaMock->expects($this->any())->method('isRequired')->willReturn(true); + $controller->method('getRequest')->willReturn($request); + $this->captchaMock->method('isRequired')->willReturn(true); $this->captchaMock->expects($this->once()) ->method('isCorrect') ->with($captchaValue) @@ -116,13 +129,13 @@ public function testCheckContactUsFormWhenCaptchaIsRequiredAndValid() ->method('resolve') ->with($request, $formId) ->willReturn($captchaValue); - $this->helperMock->expects($this->any()) - ->method('getCaptcha') - ->with($formId)->willReturn($this->captchaMock); + $this->helperMock->method('getCaptcha') + ->with($formId) + ->willReturn($this->captchaMock); $this->sessionMock->expects($this->never())->method('addErrorMessage'); $this->checkContactUsFormObserver->execute( - new \Magento\Framework\Event\Observer(['controller_action' => $controller]) + new Observer(['controller_action' => $controller]) ); } @@ -135,11 +148,10 @@ public function testCheckContactUsFormRedirectsCustomerWithWarningMessageWhenCap $redirectUrl = 'http://magento.com/contacts/'; $postData = ['name' => 'Some Name']; - $request = $this->createMock(\Magento\Framework\App\Request\Http::class); + $request = $this->createMock(Http::class); $response = $this->createMock(\Magento\Framework\App\Response\Http::class); - $request->expects($this->any()) - ->method('getPost') - ->with(\Magento\Captcha\Helper\Data::INPUT_NAME_FIELD_VALUE, null) + $request->method('getPost') + ->with(Data::INPUT_NAME_FIELD_VALUE, null) ->willReturn([$formId => $captchaValue]); $request->expects($this->once()) ->method('getPostValue') @@ -150,10 +162,10 @@ public function testCheckContactUsFormRedirectsCustomerWithWarningMessageWhenCap ->with($response, $redirectRoutePath, []) ->willReturn($redirectUrl); - $controller = $this->createMock(\Magento\Framework\App\Action\Action::class); - $controller->expects($this->any())->method('getRequest')->willReturn($request); - $controller->expects($this->any())->method('getResponse')->willReturn($response); - $this->captchaMock->expects($this->any())->method('isRequired')->willReturn(true); + $controller = $this->createMock(Action::class); + $controller->method('getRequest')->willReturn($request); + $controller->method('getResponse')->willReturn($response); + $this->captchaMock->method('isRequired')->willReturn(true); $this->captchaMock->expects($this->once()) ->method('isCorrect') ->with($captchaValue) @@ -162,32 +174,32 @@ public function testCheckContactUsFormRedirectsCustomerWithWarningMessageWhenCap ->method('resolve') ->with($request, $formId) ->willReturn($captchaValue); - $this->helperMock->expects($this->any()) - ->method('getCaptcha') + $this->helperMock->method('getCaptcha') ->with($formId) ->willReturn($this->captchaMock); - $this->messageManagerMock->expects($this->once())->method('addErrorMessage')->with($warningMessage); + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with($warningMessage); $this->actionFlagMock->expects($this->once()) ->method('set') - ->with('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true); + ->with('', Action::FLAG_NO_DISPATCH, true); $this->dataPersistorMock->expects($this->once()) ->method('set') ->with($formId, $postData); $this->checkContactUsFormObserver->execute( - new \Magento\Framework\Event\Observer(['controller_action' => $controller]) + new Observer(['controller_action' => $controller]) ); } public function testCheckContactUsFormDoesNotCheckCaptchaWhenItIsNotRequired() { - $this->helperMock->expects($this->any()) - ->method('getCaptcha') + $this->helperMock->method('getCaptcha') ->with('contact_us') ->willReturn($this->captchaMock); - $this->captchaMock->expects($this->any())->method('isRequired')->willReturn(false); + $this->captchaMock->method('isRequired')->willReturn(false); $this->captchaMock->expects($this->never())->method('isCorrect'); - $this->checkContactUsFormObserver->execute(new \Magento\Framework\Event\Observer()); + $this->checkContactUsFormObserver->execute(new Observer()); } } diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php new file mode 100644 index 0000000000000..584e7eb2e215f --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php @@ -0,0 +1,230 @@ +helperMock = $this->createMock(DataHelper::class); + $this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class); + $this->sessionMock = $this->getMockBuilder(SessionManagerInterface::class) + ->setMethods(['setEmail']) + ->getMockForAbstractClass(); + $this->actionFlagMock = $this->createMock(ActionFlag::class); + $this->messageManagerMock = $this->createMock(ManagerInterface::class); + + $objectManager = new ObjectManagerHelper($this); + $this->observer = $objectManager->getObject( + CheckUserForgotPasswordBackendObserver::class, + [ + '_helper' => $this->helperMock, + 'captchaStringResolver' => $this->captchaStringResolverMock, + '_session' => $this->sessionMock, + '_actionFlag' => $this->actionFlagMock, + 'messageManager' => $this->messageManagerMock + ] + ); + + $this->captchaMock = $this->getMockBuilder(CaptchaInterface::class) + ->setMethods(['isRequired', 'isCorrect']) + ->getMockForAbstractClass(); + $this->helperMock->expects($this->once()) + ->method('getCaptcha') + ->with($formId) + ->willReturn($this->captchaMock); + + $this->requestMock = $this->createMock(HttpRequest::class); + $this->httpResponseMock = $this->createMock(HttpResponse::class); + + $this->controllerMock = $this->getMockBuilder(Action::class) + ->disableOriginalConstructor() + ->setMethods(['getUrl', 'getRequest', 'getResponse']) + ->getMockForAbstractClass(); + $this->controllerMock->expects($this->any()) + ->method('getRequest') + ->willReturn($this->requestMock); + $this->controllerMock->expects($this->any()) + ->method('getResponse') + ->willReturn($this->httpResponseMock); + + $this->eventObserverMock = $this->createPartialMock(Observer::class, ['getControllerAction']); + $this->eventObserverMock->expects($this->any()) + ->method('getControllerAction') + ->willReturn($this->controllerMock); + } + + /** + * Test case when Captcha is required and was entered correctly. + */ + public function testExecuteWhenCaptchaIsCorrect() + { + $this->configureRequestMockWithStubValues(); + $this->captchaMock->expects($this->once())->method('isRequired')->willReturn(true); + $this->captchaMock->expects($this->once())->method('isCorrect')->willReturn(true); + + $this->executeOriginalMethodExpectsNoError(); + } + + /** + * Test case when Captcha is required and was entered incorrectly. + */ + public function testExecuteWhenCaptchaIsIncorrect() + { + $this->configureRequestMockWithStubValues(); + $this->captchaMock->expects($this->once())->method('isRequired')->willReturn(true); + $this->captchaMock->expects($this->once())->method('isCorrect')->willReturn(false); + + $this->sessionMock->expects($this->once())->method('setEmail'); + $this->actionFlagMock->expects($this->once())->method('set'); + $this->controllerMock->expects($this->once())->method('getUrl'); + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with(__('Incorrect CAPTCHA')); + $this->httpResponseMock->expects($this->once())->method('setRedirect')->willReturnSelf(); + + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when Captcha is not required. + */ + public function testExecuteWhenCaptchaIsNotRequired() + { + $this->configureRequestMockWithStubValues(); + $this->captchaMock->expects($this->once())->method('isRequired')->willReturn(false); + + $this->executeOriginalMethodExpectsNoError(); + } + + /** + * Test case when email is not provided + */ + public function testExecuteWhenEmailParamIsNotPresent() + { + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('email') + ->willReturn(null); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn(self::STUB_REQUEST_PARAMS); + $this->captchaMock->expects($this->never())->method('isRequired'); + $this->captchaMock->expects($this->never())->method('isCorrect'); + + $this->executeOriginalMethodExpectsNoError(); + } + + /** + * Stub params for Request Mock + */ + private function configureRequestMockWithStubValues() + { + $this->requestMock->expects($this->any()) + ->method('getParam') + ->with('email') + ->willReturn(self::STUB_EMAIL); + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn(self::STUB_REQUEST_PARAMS); + } + + /** + * Run original method, expect there is no error + */ + private function executeOriginalMethodExpectsNoError() + { + $this->messageManagerMock->expects($this->never())->method('addErrorMessage'); + $this->httpResponseMock->expects($this->never())->method('setRedirect'); + + $this->observer->execute($this->eventObserverMock); + } +} diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php new file mode 100644 index 0000000000000..b984daa8998f3 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php @@ -0,0 +1,53 @@ +createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); + + $resLogFactoryMock = $this->createMock(LogFactory::class); + $resLogFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($logMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createPartialMock(Observer::class, ['getUser']); + $eventMock = $this->createMock(Event::class); + $eventObserverMock->expects($this->once()) + ->method('getUser') + ->willReturn($eventMock); + + $objectManager = new ObjectManagerHelper($this); + /** @var ResetAttemptForBackendObserver $observer */ + $observer = $objectManager->getObject( + ResetAttemptForBackendObserver::class, + ['resLogFactory' => $resLogFactoryMock] + ); + $this->assertInstanceOf(Log::class, $observer->execute($eventObserverMock)); + } +} diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php new file mode 100644 index 0000000000000..11866c266845e --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php @@ -0,0 +1,52 @@ +createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); + + $resLogFactoryMock = $this->createMock(LogFactory::class); + $resLogFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($logMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createPartialMock(Observer::class, ['getModel']); + $eventObserverMock->expects($this->once()) + ->method('getModel') + ->willReturn($this->createMock(Customer::class)); + + $objectManager = new ObjectManagerHelper($this); + /** @var ResetAttemptForFrontendObserver $observer */ + $observer = $objectManager->getObject( + ResetAttemptForFrontendObserver::class, + ['resLogFactory' => $resLogFactoryMock] + ); + $this->assertInstanceOf(Log::class, $observer->execute($eventObserverMock)); + } +} diff --git a/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml b/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml index c891a578cdcca..16f2774e22ccd 100644 --- a/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml +++ b/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml @@ -11,6 +11,7 @@ + <description value="CardinalCommerce config shouldn't be visible if the 3D secure is disabled for Authorize.Net."/> <severity value="MINOR"/> @@ -21,7 +22,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set three_d_secure/cardinal/enabled_authorizenet 0" stepKey="disableCardinalCommerce"/> </after> diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php new file mode 100644 index 0000000000000..62eba5987c35d --- /dev/null +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Api; + +/** + * @api + * @since 100.0.2 + */ +interface CategoryListDeleteBySkuInterface +{ + /** + * Delete by skus list + * + * @param int $categoryId + * @param string[] $productSkuList + * @return bool + * + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + */ + public function deleteBySkus(int $categoryId, array $productSkuList): bool; +} diff --git a/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php b/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php index 8286175123fe2..84cb853ad5982 100644 --- a/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php +++ b/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php @@ -17,6 +17,7 @@ interface ProductLinkManagementInterface * * @param string $sku * @param string $type + * @throws \Magento\Framework\Exception\NoSuchEntityException * @return \Magento\Catalog\Api\Data\ProductLinkInterface[] */ public function getLinkedItemsByType($sku, $type); @@ -28,6 +29,7 @@ public function getLinkedItemsByType($sku, $type); * @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $items * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\InputException * @return bool */ public function setProductLinks($sku, array $items); diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Price/Group/AbstractGroup.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Price/Group/AbstractGroup.php index 5ffd3d1dda38d..df989c5f77174 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Price/Group/AbstractGroup.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Price/Group/AbstractGroup.php @@ -212,7 +212,7 @@ public function getCustomerGroups($groupId = null) } if ($groupId !== null) { - return isset($this->_customerGroups[$groupId]) ? $this->_customerGroups[$groupId] : []; + return $this->_customerGroups[$groupId] ?? []; } return $this->_customerGroups; diff --git a/app/code/Magento/Catalog/Block/Product/ImageFactory.php b/app/code/Magento/Catalog/Block/Product/ImageFactory.php index 172cd794edfb9..0c69a40b246bb 100644 --- a/app/code/Magento/Catalog/Block/Product/ImageFactory.php +++ b/app/code/Magento/Catalog/Block/Product/ImageFactory.php @@ -123,7 +123,7 @@ private function getLabel(Product $product, string $imageType): string if (empty($label)) { $label = $product->getName(); } - return (string) $label; + return (string)$label; } /** @@ -161,7 +161,7 @@ public function create(Product $product, string $imageId, array $attributes = nu } $attributes = $attributes === null ? [] : $attributes; - + $data = [ 'data' => [ 'template' => 'Magento_Catalog::product/image_with_borders.phtml', @@ -169,7 +169,7 @@ public function create(Product $product, string $imageId, array $attributes = nu 'width' => $imageMiscParams['image_width'], 'height' => $imageMiscParams['image_height'], 'label' => $this->getLabel($product, $imageMiscParams['image_type']), - 'ratio' => $this->getRatio($imageMiscParams['image_width'], $imageMiscParams['image_height']), + 'ratio' => $this->getRatio($imageMiscParams['image_width'] ?? 0, $imageMiscParams['image_height'] ?? 0), 'custom_attributes' => $this->getStringCustomAttributes($attributes), 'class' => $this->getClass($attributes), 'product_id' => $product->getId() diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index fb0ea680569a8..f8de9a37f4ed7 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -6,10 +6,19 @@ namespace Magento\Catalog\Model; -use Magento\Framework\Exception\InputException; +use Magento\Catalog\Api\CategoryLinkRepositoryInterface; +use Magento\Catalog\Api\CategoryListDeleteBySkuInterface; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; -class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkRepositoryInterface +/** + * @inheritdoc + */ +class CategoryLinkRepository implements CategoryLinkRepositoryInterface, CategoryListDeleteBySkuInterface { /** * @var CategoryRepository @@ -17,24 +26,32 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit protected $categoryRepository; /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface + * @var ProductRepositoryInterface */ protected $productRepository; /** - * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @var Product + */ + private $productResource; + + /** + * @param CategoryRepositoryInterface $categoryRepository + * @param ProductRepositoryInterface $productRepository + * @param Product $productResource */ public function __construct( - \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + CategoryRepositoryInterface $categoryRepository, + ProductRepositoryInterface $productRepository, + Product $productResource = null ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; + $this->productResource = $productResource ?? ObjectManager::getInstance()->get(Product::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -60,7 +77,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -68,7 +85,7 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteByIds($categoryId, $sku) { @@ -101,4 +118,44 @@ public function deleteByIds($categoryId, $sku) } return true; } + + /** + * @inheritdoc + */ + public function deleteBySkus(int $categoryId, array $productSkuList): bool + { + $category = $this->categoryRepository->get($categoryId); + $products = $this->productResource->getProductsIdsBySkus($productSkuList); + + if (!$products) { + throw new InputException(__("The category doesn't contain the specified products.")); + } + + $productPositions = $category->getProductsPosition(); + + foreach ($products as $productId) { + if (isset($productPositions[$productId])) { + unset($productPositions[$productId]); + } + } + + $category->setPostedProducts($productPositions); + + try { + $category->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException( + __( + 'Could not save products "%products" to category %category', + [ + "products" => implode(',', $productSkuList), + "category" => $category->getId() + ] + ), + $e + ); + } + + return true; + } } diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 12444c9cce202..a9907c1661bd8 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -10,6 +10,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductLinkRepositoryInterface; use Magento\Catalog\Model\Product\Attribute\Backend\Media\EntryConverterPool; +use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface; use Magento\Catalog\Model\FilterProductCustomAttribute; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\App\Filesystem\DirectoryList; @@ -108,7 +109,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements /** * Product object customization (not stored in DB) * - * @var array + * @var OptionInterface[] */ protected $_customOptions = []; @@ -2062,7 +2063,7 @@ public function addCustomOption($code, $value, $product = null) /** * Sets custom options for the product * - * @param array $options Array of options + * @param OptionInterface[] $options Array of options * @return void */ public function setCustomOptions(array $options) @@ -2073,7 +2074,7 @@ public function setCustomOptions(array $options) /** * Get all custom options of the product * - * @return array + * @return OptionInterface[] */ public function getCustomOptions() { @@ -2084,14 +2085,11 @@ public function getCustomOptions() * Get product custom option info * * @param string $code - * @return array + * @return OptionInterface|null */ public function getCustomOption($code) { - if (isset($this->_customOptions[$code])) { - return $this->_customOptions[$code]; - } - return null; + return $this->_customOptions[$code] ?? null; } /** @@ -2101,11 +2099,7 @@ public function getCustomOption($code) */ public function hasCustomOptions() { - if (count($this->_customOptions)) { - return true; - } else { - return false; - } + return (bool)count($this->_customOptions); } /** @@ -2405,16 +2399,14 @@ public function reloadPriceInfo() } } - // phpcs:disable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames /** * Return Data Object data in array format. * * @return array * @todo refactor with converter for AbstractExtensibleModel */ - public function __toArray() + public function __toArray() //phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames { - // phpcs:enable PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames $data = $this->_data; $hasToArray = function ($model) { return is_object($model) && method_exists($model, '__toArray') && is_callable([$model, '__toArray']); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php index 24abb8471d477..0da6da94fde5c 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php @@ -37,8 +37,7 @@ public function getVisibleStatusIds() } /** - * Retrieve Saleable Status Ids - * Default Product Enable status + * Retrieve Saleable Status Ids, default Product Enable status * * @return int[] */ @@ -51,6 +50,7 @@ public function getSaleableStatusIds() * Retrieve option array * * @return string[] + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getOptionArray() { @@ -83,7 +83,7 @@ public function getOptionText($optionId) { $options = self::getOptionArray(); - return isset($options[$optionId]) ? $options[$optionId] : null; + return $options[$optionId] ?? null; } /** diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index 91fb5213281ec..b04d3da8f0223 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -8,10 +8,12 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Attribute\ScopeOverriddenValue; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Catalog\Model\Product\Option\Repository as OptionRepository; use Magento\Catalog\Model\ProductFactory; use Magento\Framework\App\ObjectManager; use Magento\Framework\EntityManager\MetadataPool; +use Magento\Store\Model\Store; use Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException; /** @@ -72,40 +74,37 @@ public function __construct( /** * Create product duplicate * - * @param \Magento\Catalog\Model\Product $product - * - * @return \Magento\Catalog\Model\Product - * - * @throws \Exception + * @param Product $product + * @return Product */ - public function copy(Product $product) + public function copy(Product $product): Product { $product->getWebsiteIds(); $product->getCategoryIds(); $metadata = $this->metadataPool->getMetadata(ProductInterface::class); - /** @var \Magento\Catalog\Model\Product $duplicate */ + /** @var Product $duplicate */ $duplicate = $this->productFactory->create(); $productData = $product->getData(); $productData = $this->removeStockItem($productData); $duplicate->setData($productData); $duplicate->setOptions([]); + $duplicate->setMetaTitle(null); + $duplicate->setMetaKeyword(null); + $duplicate->setMetaDescription(null); $duplicate->setIsDuplicate(true); $duplicate->setOriginalLinkId($product->getData($metadata->getLinkField())); - $duplicate->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); + $duplicate->setStatus(Status::STATUS_DISABLED); $duplicate->setCreatedAt(null); $duplicate->setUpdatedAt(null); $duplicate->setId(null); - $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $duplicate->setStoreId(Store::DEFAULT_STORE_ID); $this->copyConstructor->build($product, $duplicate); $this->setDefaultUrl($product, $duplicate); $this->setStoresUrl($product, $duplicate); $this->optionRepository->duplicate($product, $duplicate); - $product->getResource()->duplicate( - $product->getData($metadata->getLinkField()), - $duplicate->getData($metadata->getLinkField()) - ); + return $duplicate; } @@ -118,11 +117,11 @@ public function copy(Product $product) */ private function setDefaultUrl(Product $product, Product $duplicate) : void { - $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $duplicate->setStoreId(Store::DEFAULT_STORE_ID); $resource = $product->getResource(); $attribute = $resource->getAttribute('url_key'); $productId = $product->getId(); - $urlKey = $resource->getAttributeRawValue($productId, 'url_key', \Magento\Store\Model\Store::DEFAULT_STORE_ID); + $urlKey = $resource->getAttributeRawValue($productId, 'url_key', Store::DEFAULT_STORE_ID); do { $urlKey = $this->modifyUrl($urlKey); $duplicate->setUrlKey($urlKey); @@ -175,7 +174,7 @@ private function setStoresUrl(Product $product, Product $duplicate) : void $productResource->saveAttribute($duplicate, 'url_path'); $productResource->saveAttribute($duplicate, 'url_key'); } - $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $duplicate->setStoreId(Store::DEFAULT_STORE_ID); } /** @@ -197,7 +196,7 @@ private function modifyUrl(string $urlKey) : string * @param array $productData * @return array */ - private function removeStockItem(array $productData) + private function removeStockItem(array $productData): array { if (isset($productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY])) { $extensionAttributes = $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY]; diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php b/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php index 36eb71abe2a5d..1f36b37c34f6f 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php @@ -9,6 +9,9 @@ use Magento\Catalog\Model\Product; +/** + * Manage entryes + */ class EntryResolver { /** @@ -27,7 +30,7 @@ public function getEntryFilePathById(Product $product, $entryId) foreach ($mediaGalleryData['images'] as $image) { if (isset($image['value_id']) && $image['value_id'] == $entryId) { - return isset($image['file']) ? $image['file'] : null; + return $image['file'] ?? null; } } return null; @@ -49,7 +52,7 @@ public function getEntryIdByFilePath(Product $product, $filePath) foreach ($mediaGalleryData['images'] as $image) { if (isset($image['file']) && $image['file'] == $filePath) { - return isset($image['value_id']) ? $image['value_id'] : null; + return $image['value_id'] ?? null; } } return null; diff --git a/app/code/Magento/Catalog/Model/Product/ProductFrontendAction/Synchronizer.php b/app/code/Magento/Catalog/Model/Product/ProductFrontendAction/Synchronizer.php index ec2e697ccc849..b736700a4481d 100644 --- a/app/code/Magento/Catalog/Model/Product/ProductFrontendAction/Synchronizer.php +++ b/app/code/Magento/Catalog/Model/Product/ProductFrontendAction/Synchronizer.php @@ -20,6 +20,8 @@ * * Service which allows to sync product widget information, such as product id with db. In order to reuse this info * on different devices + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Synchronizer { @@ -94,6 +96,7 @@ public function __construct( * * @param string $namespace * @return int + * @throws \Magento\Framework\Exception\LocalizedException */ private function getLifeTimeByNamespace($namespace) { @@ -119,6 +122,7 @@ private function getLifeTimeByNamespace($namespace) * @param array $productsData (product action data, that came from frontend) * @param string $typeId namespace (type of action) * @return array + * @throws \Magento\Framework\Exception\LocalizedException */ private function filterNewestActions(array $productsData, $typeId) { @@ -166,6 +170,7 @@ private function getProductIdsByActions(array $actions) * @param array $productsData * @param string $typeId * @return void + * @throws \Exception */ public function syncActions(array $productsData, $typeId) { @@ -189,8 +194,7 @@ public function syncActions(array $productsData, $typeId) foreach ($collection as $item) { $this->entityManager->delete($item); } - - foreach ($productsData as $productId => $productData) { + foreach ($productsData as $productData) { /** @var ProductFrontendActionInterface $action */ $action = $this->productFrontendActionFactory->create( [ @@ -198,7 +202,7 @@ public function syncActions(array $productsData, $typeId) 'visitor_id' => $customerId ? null : $visitorId, 'customer_id' => $this->session->getCustomerId(), 'added_at' => $productData['added_at'], - 'product_id' => $productId, + 'product_id' => $productData['product_id'], 'type_id' => $typeId ] ] diff --git a/app/code/Magento/Catalog/Model/Product/Type.php b/app/code/Magento/Catalog/Model/Product/Type.php index 4c973be20dee5..d7dc74e0d0cc3 100644 --- a/app/code/Magento/Catalog/Model/Product/Type.php +++ b/app/code/Magento/Catalog/Model/Product/Type.php @@ -6,43 +6,37 @@ namespace Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Type\Pool; +use Magento\Catalog\Model\Product\Type\Price; +use Magento\Catalog\Model\Product\Type\Price\Factory as PriceFactory; +use Magento\Catalog\Model\Product\Type\Simple; +use Magento\Catalog\Model\ProductTypes\ConfigInterface; use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\Pricing\PriceInfo\Factory as PriceInfoFactory; /** * Product type model * + * * @api * @since 100.0.2 */ class Type implements OptionSourceInterface { - /**#@+ - * Available product types - */ const TYPE_SIMPLE = 'simple'; const TYPE_BUNDLE = 'bundle'; const TYPE_VIRTUAL = 'virtual'; - /**#@-*/ - /** - * Default product type - */ const DEFAULT_TYPE = 'simple'; - /** - * Default product type model - */ - const DEFAULT_TYPE_MODEL = \Magento\Catalog\Model\Product\Type\Simple::class; + const DEFAULT_TYPE_MODEL = Simple::class; - /** - * Default price model - */ - const DEFAULT_PRICE_MODEL = \Magento\Catalog\Model\Product\Type\Price::class; + const DEFAULT_PRICE_MODEL = Price::class; /** - * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface + * @var ConfigInterface */ protected $_config; @@ -77,35 +71,35 @@ class Type implements OptionSourceInterface /** * Product type factory * - * @var \Magento\Catalog\Model\Product\Type\Pool + * @var Pool */ protected $_productTypePool; /** * Price model factory * - * @var \Magento\Catalog\Model\Product\Type\Price\Factory + * @var PriceFactory */ protected $_priceFactory; /** - * @var \Magento\Framework\Pricing\PriceInfo\Factory + * @var PriceInfoFactory */ protected $_priceInfoFactory; /** * Construct * - * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $config - * @param \Magento\Catalog\Model\Product\Type\Pool $productTypePool - * @param \Magento\Catalog\Model\Product\Type\Price\Factory $priceFactory - * @param \Magento\Framework\Pricing\PriceInfo\Factory $priceInfoFactory + * @param ConfigInterface $config + * @param Pool $productTypePool + * @param PriceFactory $priceFactory + * @param PriceInfoFactory $priceInfoFactory */ public function __construct( - \Magento\Catalog\Model\ProductTypes\ConfigInterface $config, - \Magento\Catalog\Model\Product\Type\Pool $productTypePool, - \Magento\Catalog\Model\Product\Type\Price\Factory $priceFactory, - \Magento\Framework\Pricing\PriceInfo\Factory $priceInfoFactory + ConfigInterface $config, + Pool $productTypePool, + PriceFactory $priceFactory, + PriceInfoFactory $priceInfoFactory ) { $this->_config = $config; $this->_productTypePool = $productTypePool; @@ -116,8 +110,8 @@ public function __construct( /** * Factory to product singleton product type instances * - * @param \Magento\Catalog\Model\Product $product - * @return \Magento\Catalog\Model\Product\Type\AbstractType + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Catalog\Model\Product\Type\AbstractType */ public function factory($product) { @@ -139,8 +133,8 @@ public function factory($product) /** * Product type price model factory * - * @param string $productType - * @return \Magento\Catalog\Model\Product\Type\Price + * @param string $productType + * @return \Magento\Catalog\Model\Product\Type\Price */ public function priceFactory($productType) { diff --git a/app/code/Magento/Catalog/Model/Product/Visibility.php b/app/code/Magento/Catalog/Model/Product/Visibility.php index c05bda7838d78..cd1500406df44 100644 --- a/app/code/Magento/Catalog/Model/Product/Visibility.php +++ b/app/code/Magento/Catalog/Model/Product/Visibility.php @@ -133,7 +133,7 @@ public static function getAllOptions() public static function getOptionText($optionId) { $options = self::getOptionArray(); - return isset($options[$optionId]) ? $options[$optionId] : null; + return $options[$optionId] ?? null; } //phpcs:enable Magento2.Functions.StaticFunction diff --git a/app/code/Magento/Catalog/Model/Product/Webapi/ProductOutputProcessor.php b/app/code/Magento/Catalog/Model/Product/Webapi/ProductOutputProcessor.php new file mode 100644 index 0000000000000..4d683829219ba --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Webapi/ProductOutputProcessor.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Webapi; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Webapi\Request; +use Magento\Framework\Webapi\Rest\Request\DeserializerInterface; + +/** + * Class for checking empty array and remove it from the output result + */ +class ProductOutputProcessor +{ + /** + * @var Request + */ + private $request; + + /** + * @var DeserializerInterface + */ + private $deserializer; + + /** + * @param Request $request + * @param DeserializerInterface $deserializer + */ + public function __construct( + Request $request, + DeserializerInterface $deserializer + ) { + $this->request = $request; + $this->deserializer = $deserializer; + } + + /** + * Removing attribute from the result array if its null or empty + * + * @param ProductInterface $product + * @param array $result + * @return array + */ + public function execute( + ProductInterface $product, + array $result + ): array { + $requestContent = $this->request->getContent() ?? []; + if (empty($requestContent)) { + return $result; + } + $requestContentDetails = (array)$this->deserializer->deserialize($requestContent); + $requestProductList = $this->extractProductList($requestContentDetails); + + $requestProductList = array_filter( + $requestProductList, + function ($requestProduct) use ($product) { + return isset($requestProduct['sku']) && $requestProduct['sku'] === $product->getSku(); + } + ); + + if (empty($requestProductList)) { + return $result; + } + + $requestProduct = current($requestProductList); + + if (empty($product->getTierPrices()) && !array_key_exists('tier_prices', $requestProduct)) { + unset($result['tier_prices']); + } + + if (empty($product->getProductLinks()) && !array_key_exists('product_links', $requestProduct)) { + unset($result['product_links']); + } + + return $result; + } + + /** + * Extract product list from the request content details + * + * @param array $contentDetails + * @return array + */ + private function extractProductList(array $contentDetails): array + { + $productList = []; + $arrayIterator = new \RecursiveArrayIterator($contentDetails); + $iterator = new \RecursiveIteratorIterator($arrayIterator, \RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $iteratorKey => $iteratorValue) { + if ($iteratorKey === 'product') { + array_push($productList, $iteratorValue); + } + } + return $productList; + } +} diff --git a/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php b/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php index f58d1d6b69be8..a50c650e8b264 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php @@ -6,6 +6,9 @@ namespace Magento\Catalog\Model\ProductLink\Converter; +/** + * Return converter by link type + */ class ConverterPool { /** @@ -34,8 +37,6 @@ public function __construct(array $converters) */ public function getConverter($linkType) { - return isset($this->converters[$linkType]) - ? $this->converters[$linkType] - : $this->converters[$this->defaultConverterCode]; + return $this->converters[$linkType] ?? $this->converters[$this->defaultConverterCode]; } } diff --git a/app/code/Magento/Catalog/Model/ProductLink/Link.php b/app/code/Magento/Catalog/Model/ProductLink/Link.php index ebf90c0523818..48945fbef9d52 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Link.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Link.php @@ -7,6 +7,8 @@ namespace Magento\Catalog\Model\ProductLink; /** + * @inheritdoc + * * @codeCoverageIgnore */ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements @@ -30,7 +32,7 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements */ protected function _get($key) { - return isset($this->_data[$key]) ? $this->_data[$key] : null; + return $this->_data[$key] ?? null; } /** @@ -38,9 +40,11 @@ protected function _get($key) * * @return array * @todo refactor with converter for AbstractExtensibleModel + * phpcs:disable */ public function __toArray() { + //phpcs:enable $data = $this->_data; $hasToArray = function ($model) { return is_object($model) && method_exists($model, '__toArray') && is_callable([$model, '__toArray']); @@ -169,7 +173,7 @@ public function setPosition($position) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Catalog\Api\Data\ProductLinkExtensionInterface|null */ @@ -184,7 +188,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Catalog\Api\Data\ProductLinkExtensionInterface $extensionAttributes * @return $this diff --git a/app/code/Magento/Catalog/Model/ProductLink/Management.php b/app/code/Magento/Catalog/Model/ProductLink/Management.php index 066549274b07c..017985e3f549f 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Management.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Management.php @@ -6,37 +6,42 @@ namespace Magento\Catalog\Model\ProductLink; -use Magento\Catalog\Api\Data; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\InputException; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\LinkTypeProvider; +use Magento\Catalog\Api\ProductLinkManagementInterface; -class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface +/** + * Manage product links from api + */ +class Management implements ProductLinkManagementInterface { /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface + * @var ProductRepositoryInterface */ protected $productRepository; /** - * @var \Magento\Catalog\Model\Product\LinkTypeProvider + * @var LinkTypeProvider */ protected $linkTypeProvider; /** - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider + * @param ProductRepositoryInterface $productRepository + * @param LinkTypeProvider $linkTypeProvider */ public function __construct( - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider + ProductRepositoryInterface $productRepository, + LinkTypeProvider $linkTypeProvider ) { $this->productRepository = $productRepository; $this->linkTypeProvider = $linkTypeProvider; } /** - * {@inheritdoc} + * @inheritdoc */ public function getLinkedItemsByType($sku, $type) { @@ -63,47 +68,42 @@ public function getLinkedItemsByType($sku, $type) } /** - * {@inheritdoc} + * @inheritdoc */ public function setProductLinks($sku, array $items) { + + if (empty($items)) { + throw InputException::invalidFieldValue('items', 'empty array'); + } + $linkTypes = $this->linkTypeProvider->getLinkTypes(); // Check if product link type is set and correct - if (!empty($items)) { - foreach ($items as $newLink) { - $type = $newLink->getLinkType(); - if ($type == null) { - throw InputException::requiredField("linkType"); - } - if (!isset($linkTypes[$type])) { - throw new NoSuchEntityException( - __('The "%1" link type wasn\'t found. Verify the type and try again.', $type) - ); - } + foreach ($items as $newLink) { + $type = $newLink->getLinkType(); + if ($type == null) { + throw InputException::requiredField("linkType"); + } + if (!isset($linkTypes[$type])) { + throw new NoSuchEntityException( + __('The "%1" link type wasn\'t found. Verify the type and try again.', $type) + ); } } $product = $this->productRepository->get($sku); - // Replace only links of the specified type $existingLinks = $product->getProductLinks(); - $newLinks = []; - if (!empty($existingLinks)) { - foreach ($existingLinks as $link) { - if ($link->getLinkType() != $type) { - $newLinks[] = $link; - } - } - $newLinks = array_merge($newLinks, $items); - } else { - $newLinks = $items; - } + $newLinks = array_merge($existingLinks, $items); + $product->setProductLinks($newLinks); try { $this->productRepository->save($product); } catch (\Exception $exception) { - throw new CouldNotSaveException(__('The linked products data is invalid. Verify the data and try again.')); + throw new CouldNotSaveException( + __('The linked products data is invalid. Verify the data and try again.') + ); } return true; diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index e31180d4ff6cf..14daac0147abf 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -1904,6 +1904,7 @@ protected function _productLimitationJoinPrice() * @see \Magento\Catalog\Model\ResourceModel\Product\Collection::_productLimitationJoinPrice() * @param bool $joinLeft * @return $this + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _productLimitationPrice($joinLeft = false) { @@ -1922,14 +1923,14 @@ protected function _productLimitationPrice($joinLeft = false) $connection = $this->getConnection(); $select = $this->getSelect(); - $joinCond = join( - ' AND ', - [ - 'price_index.entity_id = e.entity_id', - $connection->quoteInto('price_index.website_id = ?', $filters['website_id']), - $connection->quoteInto('price_index.customer_group_id = ?', $filters['customer_group_id']) - ] - ); + $joinCondArray = []; + $joinCondArray[] = 'price_index.entity_id = e.entity_id'; + $joinCondArray[] = $connection->quoteInto('price_index.customer_group_id = ?', $filters['customer_group_id']); + // Add website condition only if it's different from admin scope + if (((int) $filters['website_id']) !== Store::DEFAULT_STORE_ID) { + $joinCondArray[] = $connection->quoteInto('price_index.website_id = ?', $filters['website_id']); + } + $joinCond = join(' AND ', $joinCondArray); $fromPart = $select->getPart(\Magento\Framework\DB\Select::FROM); if (!isset($fromPart['price_index'])) { @@ -2121,7 +2122,9 @@ private function getChildrenCategories(int $categoryId): array if (in_array($category['parent_id'], $categoryIds) && in_array($category['parent_id'], $anchorCategory)) { $categoryIds[] = (int)$category[$linkField]; - if ($category['is_anchor'] == 1) { + // Storefront approach is to treat non-anchor children of anchor category as anchors. + // Adding their's IDs to $anchorCategory for consistency. + if ($category['is_anchor'] == 1 || in_array($category['parent_id'], $anchorCategory)) { $anchorCategory[] = (int)$category[$linkField]; } } diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductToCategoryActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductToCategoryActionGroup.xml new file mode 100644 index 0000000000000..bedd55e183290 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAddProductToCategoryActionGroup.xml @@ -0,0 +1,25 @@ +<?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="AdminAddProductToCategoryActionGroup"> + <annotations> + <description>Add Product to Category</description> + </annotations> + <arguments> + <argument name="product"/> + </arguments> + + <scrollTo selector="{{AdminCategoryBasicFieldSection.productsInCategory}}" x="0" y="-80" stepKey="scrollToProductInCategory"/> + <click selector="{{AdminCategoryBasicFieldSection.productsInCategory}}" stepKey="clickOnProductInCategory"/> + <fillField selector="{{AdminCategoryContentSection.productTableColumnName}}" userInput="{{product.name}}" stepKey="selectProduct"/> + <click selector="{{AdminCategoryContentSection.productSearch}}" stepKey="clickSearchButton"/> + <click selector="{{AdminCategoryContentSection.productTableRow}}" stepKey="selectProductFromTableRow"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml new file mode 100644 index 0000000000000..67c68e03fcfa1 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AdminCategoryPageOpenProductsInCategorySectionActionGroup"> + <annotations> + <description>Open 'Products in Category' section on category edit page in Admin.</description> + </annotations> + + <conditionalClick selector="{{AdminCategoryProductsSection.sectionHeader}}" dependentSelector="{{AdminCategoryProductsSection.sectionBody}}" visible="false" stepKey="openSectionIfHidden" /> + <scrollTo selector="{{AdminCategoryProductsSection.sectionHeader}}" stepKey="scrollToSection" /> + <waitForPageLoad stepKey="waitSectionFullyLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml new file mode 100644 index 0000000000000..7b453735994d7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -0,0 +1,31 @@ +<?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="AdminDeleteProductAttributeByLabelActionGroup"> + <annotations> + <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> + </annotations> + <arguments> + <argument name="productAttributeLabel" type="string" defaultValue="{{ProductAttributeFrontendLabel.label}}"/> + </arguments> + + <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> + <waitForPageLoad stepKey="waitForProductAttributeGridPageLoad"/> + <click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="resetFiltersOnGrid"/> + <fillField selector="{{AdminProductAttributeGridSection.attributeLabelFilter}}" userInput="{{productAttributeLabel}}" stepKey="setAttributeLabelFilter"/> + <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeLabelFromTheGrid"/> + <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/> + <click selector="{{AttributePropertiesSection.DeleteAttribute}}" stepKey="clickOnDeleteAttributeButton"/> + <waitForElementVisible selector="{{AdminConfirmationModalSection.message}}" stepKey="waitForConfirmationPopUpVisible"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="clickOnConfirmationButton"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageVisible"/> + <see selector="{{AdminMessagesSection.success}}" userInput="{{ProductAttributeMessages.remove_success}}" stepKey="seeAttributeDeleteSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml new file mode 100644 index 0000000000000..f823db0a86548 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml @@ -0,0 +1,34 @@ +<?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="AdminProductFormAdvancedPricingAddTierPriceActionGroup"> + <annotations> + <description>Add new tier price on Advanced Pricing dialog on the Admin Product creation/edit page.</description> + </annotations> + <arguments> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForGroupPriceAddButtonAppears"/> + <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" stepKey="waitForPriceWebsiteInputAppears"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceWebsite}}" userInput="{{website}}" stepKey="selectWebsite"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceCustomerGroup}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup"/> + <fillField selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceQty}}" userInput="{{quantity}}" stepKey="fillQuantity"/> + <selectOption selector="{{AdminProductFormAdvancedPricingSection.lastTierPriceType}}" userInput="{{priceType}}" stepKey="selectPriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.lastTierPriceDiscountAmount}}" : "{{AdminProductFormAdvancedPricingSection.lastTierPriceFixedAmount}}"" stepKey="priceAmountSelector"/> + <waitForElementVisible selector="{$priceAmountSelector}" stepKey="waitPriceAmountFieldAppers"/> + <fillField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="fillPriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..03c98c1cb17b7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AdminProductFormCloseAdvancedPricingDialogActionGroup"> + <annotations> + <description>Close Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickCloseButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..10f2d32799200 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AdminProductFormDoneAdvancedPricingDialogActionGroup"> + <annotations> + <description>Done Advanced Pricing dialog from product form.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml new file mode 100644 index 0000000000000..1c96ce3469485 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AdminProductFormOpenAdvancedPricingDialogActionGroup"> + <annotations> + <description>Open Advanced Pricing dialog from product form.</description> + </annotations> + + <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" stepKey="waitForModalTitleAppears"/> + <see selector="{{AdminProductFormAdvancedPricingSection.modalTitle}}" userInput="Advanced Pricing" stepKey="checkModalTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml new file mode 100644 index 0000000000000..564033f459dc9 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AdminSaveCategoryFormActionGroup"> + <annotations> + <description>Save category edit form in Admin and check success message.</description> + </annotations> + + <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="saveCategory"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppears"/> + <see userInput="You saved the category." selector="{{AdminMessagesSection.success}}" stepKey="assertSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetUseInSearchValueForProductAttributeActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetUseInSearchValueForProductAttributeActionGroup.xml new file mode 100644 index 0000000000000..d5c2ed847e33f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetUseInSearchValueForProductAttributeActionGroup.xml @@ -0,0 +1,23 @@ +<?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="AdminSetUseInSearchValueForProductAttributeActionGroup"> + <annotations> + <description>Set 'Use In Search' value for product attribute</description> + </annotations> + <arguments> + <argument name="useInSearchValue" type="string" defaultValue="Yes"/> + </arguments> + + <scrollToTopOfPage stepKey="scrollToTopOfPage"/> + <click selector="{{StorefrontPropertiesSection.StoreFrontPropertiesTab}}" stepKey="clickStorefrontPropertiesTab"/> + <waitForElementVisible selector="{{AdvancedAttributePropertiesSection.UseInSearch}}" stepKey="waitForUseInSearchElementVisible"/> + <selectOption selector="{{AdvancedAttributePropertiesSection.UseInSearch}}" userInput="{{useInSearchValue}}" stepKey="setUseInSearchValue"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml new file mode 100644 index 0000000000000..42aee90882400 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml @@ -0,0 +1,32 @@ +<?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="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup"> + <annotations> + <description>Check AdvancedPricing tier price row.</description> + </annotations> + <arguments> + <argument name="rowNumber" type="string" defaultValue="0"/> + <argument name="website" type="string" defaultValue="All Websites [USD]"/> + <argument name="customerGroup" type="string" defaultValue="ALL GROUPS"/> + <argument name="quantity" type="string" defaultValue="1"/> + <argument name="priceType" type="string" defaultValue="Fixed"/> + <argument name="amount" type="string" defaultValue="10"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" stepKey="waitForPricesGridAppears"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect(rowNumber)}}" userInput="{{website}}" stepKey="seeWebsite"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect(rowNumber)}}" userInput="{{customerGroup}}" stepKey="seeCustomerGroup"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput(rowNumber)}}" userInput="{{quantity}}" stepKey="seeQuantity"/> + <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceValueTypeSelect(rowNumber)}}" userInput="{{priceType}}" stepKey="seePriceType"/> + <executeJS function="return '{{priceType}}' == 'Discount' ? "{{AdminProductFormAdvancedPricingSection.productTierPricePercentageValuePriceInput(rowNumber)}}" : "{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput(rowNumber)}}"" stepKey="priceAmountSelector"/> + <seeInField selector="{$priceAmountSelector}" userInput="{{amount}}" stepKey="seePriceAmount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductOnCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductOnCategoryPageActionGroup.xml index d35d6a4778dd6..4bd2c97af7afb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductOnCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertProductOnCategoryPageActionGroup.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertProductOnCategoryPageActionGroup" extends="StorefrontCheckCategorySimpleProductActionGroup"> <annotations> - <description>EXTENDS:StorefrontCheckCategorySimpleProduct. Removes 'AssertProductPrice', 'moveMouseOverProduct', 'AssertAddToCart'</description> + <description>DEPRECATED. Use AssertStorefrontProductIsPresentOnCategoryPageActionGroup. + EXTENDS:StorefrontCheckCategorySimpleProduct. Removes 'AssertProductPrice', 'moveMouseOverProduct', 'AssertAddToCart'</description> </annotations> <remove keyForRemoval="AssertProductPrice"/> <remove keyForRemoval="moveMouseOverProduct"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml new file mode 100644 index 0000000000000..a2940708eeb84 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml @@ -0,0 +1,26 @@ +<?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"> + <!-- Check simple product on the category page --> + <actionGroup name="AssertStorefrontCategorySimpleProductShownActionGroup"> + <annotations> + <description>Validate that the provided Simple Product is present and correct on a Category page.</description> + </annotations> + <arguments> + <argument name="productName" type="string" defaultValue="{{ApiSimpleOne.name}}"/> + <argument name="productPrice" type="string" defaultValue="{{ApiSimpleOne.price}}"/> + </arguments> + + <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="waitForProduct"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="assertProductName"/> + <see userInput="${{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(productName)}}" stepKey="moveMouseOverProduct"/> + <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(productName)}}" stepKey="assertAddToCartButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml new file mode 100644 index 0000000000000..226bb8468d62e --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup"> + <annotations> + <description>Validate that the Product Controls Are Not Visible On Category Page Without Hover on Product</description> + </annotations> + + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsNotVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml new file mode 100644 index 0000000000000..60d56df04bd2f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup"> + <annotations> + <description>Validate that the Product Controls Are Visible on Category Page on Hover on Product</description> + </annotations> + + <seeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageFinalPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageFinalPriceActionGroup.xml new file mode 100644 index 0000000000000..cf327266909d3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageFinalPriceActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AssertStorefrontProductDetailPageFinalPriceActionGroup"> + <arguments> + <argument name="finalProductPrice" type="string"/> + </arguments> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.price}}" stepKey="productPriceText"/> + <assertEquals stepKey="assertProductPriceOnProductPage"> + <expectedResult type="string">${{finalProductPrice}}</expectedResult> + <actualResult type="variable">productPriceText</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameActionGroup.xml new file mode 100644 index 0000000000000..7ed38153cc446 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AssertStorefrontProductDetailPageNameActionGroup"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="productNameText"/> + <assertEquals stepKey="assertProductNameOnProductPage"> + <expectedResult type="string">{{productName}}</expectedResult> + <actualResult type="variable">productNameText</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageTierPriceActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageTierPriceActionGroup.xml new file mode 100644 index 0000000000000..47ef781271ade --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageTierPriceActionGroup.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="AssertStorefrontProductDetailPageTierPriceActionGroup"> + <arguments> + <argument name="tierProductPriceDiscountQuantity" type="string"/> + <argument name="productPriceWithAppliedTierPriceDiscount" type="string"/> + <argument name="productSavedPricePercent" type="string"/> + </arguments> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> + <assertEquals stepKey="assertTierPriceTextOnProductPage"> + <expectedResult type="string">Buy {{tierProductPriceDiscountQuantity}} for ${{productPriceWithAppliedTierPriceDiscount}} each and save {{productSavedPricePercent}}%</expectedResult> + <actualResult type="variable">tierPriceText</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductIsPresentOnCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductIsPresentOnCategoryPageActionGroup.xml new file mode 100644 index 0000000000000..7c10be74b1b79 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductIsPresentOnCategoryPageActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AssertStorefrontProductIsPresentOnCategoryPageActionGroup"> + <annotations> + <description>Validate that the provided Product is present and has correct name on a Category page.</description> + </annotations> + <arguments> + <argument name="productName" type="string" defaultValue="{{ApiSimpleOne.name}}"/> + </arguments> + + <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(productName)}}" stepKey="assertProductName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml new file mode 100644 index 0000000000000..87f6e6e705263 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml @@ -0,0 +1,25 @@ +<?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="AssertStorefrontProductPriceInCategoryPageActionGroup"> + <annotations> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price is present and correct.</description> + </annotations> + <arguments> + <argument name="categoryUrl" type="string" defaultValue="{{SimpleRootSubCategory.url_key}}"/> + <argument name="productName" type="string" defaultValue="{{productWithHTMLEntityOne.name}}"/> + <argument name="productPrice" type="string" defaultValue="{{productWithHTMLEntityOne.price}}"/> + </arguments> + + <amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="navigateToCategoryPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + <see userInput="{{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml new file mode 100644 index 0000000000000..b2a7d5f96ec94 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" extends="AssertStorefrontProductPriceInCategoryPageActionGroup"> + <annotations> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price and special price are correct.</description> + </annotations> + <arguments> + <argument name="productSpecialPrice" type="string" defaultValue="{{updateVirtualProductSpecialPrice.special_price}}"/> + </arguments> + + <see userInput="{{productSpecialPrice}}" selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName(productName)}}" after="assertProductPrice" stepKey="assertProductSpecialPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml index fb78909eab0b6..15c3d55fb9382 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/DeleteProductAttributeByLabelActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="DeleteProductAttributeByLabelActionGroup"> <annotations> - <description>Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> + <description>DEPRECATED. Please use AdminDeleteProductAttributeByLabelActionGroup instead. Goes to the Admin Product Attributes grid page. Filters the grid for the provided Product Attribute (Label). Deletes the Product Attribute from the grid. Validates that the Success Message is present.</description> </annotations> <arguments> <argument name="ProductAttribute"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FillAdminSimpleProductFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FillAdminSimpleProductFormActionGroup.xml index 2abfc546e6bb3..ef4f30e353946 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FillAdminSimpleProductFormActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/FillAdminSimpleProductFormActionGroup.xml @@ -24,6 +24,7 @@ <fillField userInput="{{simpleProduct.sku}}" selector="{{AdminProductFormSection.productSku}}" stepKey="fillSKU"/> <fillField userInput="{{simpleProduct.price}}" selector="{{AdminProductFormSection.productPrice}}" stepKey="fillPrice"/> <fillField userInput="{{simpleProduct.quantity}}" selector="{{AdminProductFormSection.productQuantity}}" stepKey="fillQuantity"/> + <selectOption userInput="{{simpleProduct.visibility}}" selector="{{AdminProductFormSection.visibility}}" stepKey="fillVisibility"/> <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[{{category.name}}]" stepKey="searchAndSelectCategory"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> <fillField userInput="{{simpleProduct.urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml index 95bda64202159..0f7145b607f6e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/ProductSetAdvancedPricingActionGroup.xml @@ -21,7 +21,7 @@ </arguments> <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickOnAdvancedPricingButton"/> - <waitForElement selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> + <waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="waitForCustomerGroupPriceAddButton"/> <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="addCustomerGroupAllGroupsQty1PriceDiscountAnd10percent"/> <waitForElement selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" stepKey="waitForSelectCustomerGroupNameAttribute2"/> <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{website}}" stepKey="selectProductWebsiteValue"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml index ff6afb4aaf0e9..19f11a2402f56 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SaveCategoryFormActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SaveCategoryFormActionGroup"> <annotations> - <description>Requires navigation to the Category creation/edit page. Checks that the url contains the AdminCategoryPage url. Saves the Category.</description> + <description>DEPRECATED. Use AdminSaveCategoryFormActionGroup instead. Requires navigation to the Category creation/edit page. Checks that the url contains the AdminCategoryPage url. Saves the Category.</description> </annotations> <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> - <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/> - <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="saveCategory"/> + <seeElement selector="{{AdminMessagesSection.success}}" stepKey="assertSuccess"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml index d4c654523a40b..1882063081f04 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/SetProductUrlKeyByStringActionGroup.xml @@ -16,7 +16,7 @@ <argument name="urlKey" type="string"/> </arguments> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.urlKeyInput}}" visible="false" stepKey="openSeoSection"/> <fillField userInput="{{urlKey}}" selector="{{AdminProductSEOSection.urlKeyInput}}" stepKey="fillUrlKey"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml index 39cb9ef1a63d4..dab5142c557ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateCategoryPageActionGroup.xml @@ -13,5 +13,6 @@ </arguments> <!-- Open category page on storefront --> <amOnPage url="{{StorefrontCategoryPage.url(category.custom_attributes[url_key])}}" stepKey="navigateStorefrontCategoryPage"/> + <waitForPageLoad stepKey="waitForCategoryPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml new file mode 100644 index 0000000000000..834abdad497b8 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="ProductAttributeMessages"> + <data key="remove_success">You deleted the product attribute.</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 46bb6e527608f..a44db8010a822 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -9,13 +9,13 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="_defaultProduct" type="product"> + <data key="name" unique="suffix">testProductName</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">testProductName</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <data key="weight">1</data> @@ -23,13 +23,13 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="ApiSimpleProduct" type="product"> + <data key="name" unique="suffix">Api Simple Product</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -55,15 +55,15 @@ <data key="urlKey" unique="suffix">api-simple-product</data> </entity> <entity name="SimpleProduct" type="product"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku" unique="suffix">SimpleProduct</data> + <data key="urlKey" unique="suffix">simpleproduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">123.00</data> <data key="visibility">4</data> <data key="status">1</data> <data key="quantity">1000</data> - <data key="urlKey" unique="suffix">simpleproduct</data> <data key="weight">1</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> @@ -72,10 +72,10 @@ <data key="name">SimpleProduct -+~/\\<>\’“:*\$#@()!,.?`=%&^</data> </entity> <entity name="SimpleProductBeforeUpdate" type="product"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku">simpleProduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">123.00</data> <data key="visibility">4</data> <data key="status">1</data> @@ -86,10 +86,10 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProductAfterImport1" type="product"> + <data key="name">SimpleProductAfterImport1</data> <data key="sku">SimpleProductForTest1</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name">SimpleProductAfterImport1</data> <data key="price">250.00</data> <data key="visibility">4</data> <data key="status">1</data> @@ -100,49 +100,50 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProductAfterImport2" type="product"> + <data key="name">SimpleProductAfterImport2</data> <data key="sku">SimpleProductForTest2</data> + <data key="urlKey">simple-product-for-test-2</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name">SimpleProductAfterImport2</data> <data key="price">300.00</data> <data key="visibility">4</data> <data key="status">1</data> <data key="quantity">100</data> - <data key="urlKey">simple-product-for-test-2</data> <data key="weight">1</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProductAfterImport3" type="product"> + <data key="name">SimpleProductAfterImport3</data> <data key="sku">SimpleProductForTest3</data> + <data key="urlKey">simple-product-for-test-3</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name">SimpleProductAfterImport3</data> <data key="price">350.00</data> <data key="visibility">4</data> <data key="status">1</data> <data key="quantity">100</data> - <data key="urlKey">simple-product-for-test-3</data> <data key="weight">1</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProduct2" type="product"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku" unique="suffix">SimpleProduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">123.00</data> <data key="visibility">4</data> <data key="status">1</data> <data key="quantity">1000</data> + <data key="weight">1</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> <entity name="SimpleProduct3" type="product"> + <data key="name" unique="suffix">simple</data> <data key="sku" unique="suffix">simple</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">simple</data> <data key="price">123.00</data> <data key="visibility">4</data> <data key="status">1</data> @@ -152,70 +153,81 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProduct4" type="product"> + <data key="name" unique="suffix">OutOfStockProduct</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">OutOfStockProduct</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">0</data> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleOutOfStockProduct" type="product"> + <data key="name" unique="suffix">OutOfStockProduct</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">OutOfStockProduct</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">0</data> </entity> <entity name="SimpleProductInStockQuantityZero" type="product"> + <data key="name" unique="suffix">SimpleProductInStockQuantityZero</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">SimpleProductInStockQuantityZero</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">SimpleProductInStockQuantityZero</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">SimpleProductInStockQuantityZero</data> <data key="status">1</data> <data key="quantity">0</data> <requiredEntity type="product_extension_attribute">EavStock0</requiredEntity> </entity> <!-- Simple Product Disabled --> <entity name="SimpleProductOffline" type="product2"> + <data key="name" unique="suffix">SimpleOffline</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">SimpleOffline</data> <data key="price">123.00</data> <data key="status">2</data> <data key="quantity">100</data> - <data key="urlKey" unique="suffix">testurlkey</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="SimpleProductDisabled" type="product"> + <data key="name" unique="suffix">Simple Product Disabled</data> <data key="sku" unique="suffix">simple_product_disabled</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">Simple Product Disabled</data> <data key="price">123.00</data> <data key="visibility">4</data> <data key="status">2</data> <data key="quantity">1001</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> + <entity name="SimpleProductDisabledStockQuantityZero" type="product"> + <data key="sku" unique="suffix">testSku</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="name" unique="suffix">Simple Product Disabled Quantity Zero</data> + <data key="price">123.00</data> + <data key="visibility">4</data> + <data key="status">2</data> + <data key="quantity">0</data> + <requiredEntity type="product_extension_attribute">EavStock0</requiredEntity> + </entity> <entity name="SimpleProductNotVisibleIndividually" type="product"> + <data key="name" unique="suffix">Simple Product Not Visible Individually</data> <data key="sku" unique="suffix">simple_product_not_visible_individually</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">Simple Product Not Visible Individually</data> <data key="price">123.00</data> <data key="visibility">1</data> <data key="status">1</data> @@ -226,10 +238,10 @@ <data key="price">321.00</data> </entity> <entity name="SimpleOne" type="product2"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku" unique="suffix">SimpleOne</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">1.23</data> <data key="visibility">4</data> <data key="status">1</data> @@ -237,25 +249,25 @@ <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="ApiSimpleOutOfStock" type="product2"> + <data key="name" unique="suffix">Api Simple Out Of Stock Product</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Out Of Stock Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="ApiSimpleOne" type="product2"> + <data key="name" unique="suffix">Api Simple Product</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -265,26 +277,26 @@ <data key="sku" unique="suffix">pr</data> </entity> <entity name="ApiSimpleOneHidden" type="product2"> + <data key="name" unique="suffix">Api Simple Product</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">1</data> - <data key="name" unique="suffix">Api Simple Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="ApiSimpleTwo" type="product2"> + <data key="name" unique="suffix">Api Simple Product Two</data> <data key="sku" unique="suffix">api-simple-product-two</data> + <data key="urlKey" unique="suffix">api-simple-product-two</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Product Two</data> <data key="price">234.00</data> - <data key="urlKey" unique="suffix">api-simple-product-two</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -300,23 +312,23 @@ <data key="price">70</data> </entity> <entity name="ApiSimpleTwoHidden" type="product2"> + <data key="name" unique="suffix">Api Simple Product Two</data> <data key="sku" unique="suffix">api-simple-product-two</data> + <data key="urlKey" unique="suffix">api-simple-product-two</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">1</data> - <data key="name" unique="suffix">Api Simple Product Two</data> <data key="price">234.00</data> - <data key="urlKey" unique="suffix">api-simple-product-two</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="VirtualProduct" type="product"> + <data key="name" unique="suffix">VirtualProduct</data> <data key="sku" unique="suffix">virtualproduct</data> <data key="type_id">virtual</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">VirtualProduct</data> <data key="price">99.99</data> <data key="quantity">250</data> <data key="weight">0</data> @@ -324,10 +336,10 @@ <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> </entity> <entity name="SimpleTwo" type="product2"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku" unique="suffix">SimpleTwo</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">1.23</data> <data key="visibility">4</data> <data key="status">1</data> @@ -378,52 +390,52 @@ <data key="filename">test_image</data> </entity> <entity name="ProductWithUnicode" type="product"> + <data key="name" unique="suffix">霁产品</data> <data key="sku" unique="suffix">霁产品</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">霁产品</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="productWithHTMLEntityOne" type="product"> + <data key="name" unique="suffix">SimpleOne™Product</data> <data key="sku" unique="suffix">SimpleOne™Product</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">SimpleOne™Product</data> <data key="price">50.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="productWithHTMLEntityTwo" type="product"> + <data key="name" unique="suffix">SimpleTwo霁产品<カネボウPro</data> <data key="sku" unique="suffix">SimpleTwo霁产品<カネボウPro</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">SimpleTwo霁产品<カネボウPro</data> <data key="price">50.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="defaultVirtualProduct" type="product"> + <data key="name" unique="suffix">virtualProduct</data> <data key="sku" unique="suffix">virtualProduct</data> + <data key="urlKey" unique="suffix">virtualproduct</data> <data key="type_id">virtual</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">virtualProduct</data> <data key="price">12.34</data> - <data key="urlKey" unique="suffix">virtualproduct</data> <data key="status">1</data> <data key="quantity">100</data> <data key="weight">0</data> @@ -431,13 +443,13 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="productWithDescription" type="product"> + <data key="name" unique="suffix">testProductWithDescriptionName</data> <data key="sku" unique="suffix">testProductWithDescriptionSku</data> + <data key="urlKey" unique="suffix">testproductwithdescriptionurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">testProductWithDescriptionName</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testproductwithdescriptionurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -446,13 +458,13 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="ApiProductWithDescription" type="product"> + <data key="name" unique="suffix">Api Simple Product</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -460,13 +472,13 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="ApiProductNameWithNoSpaces" type="product"> + <data key="name" unique="suffix">ApiSimpleProduct</data> <data key="sku" unique="suffix">api-simple-product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">ApiSimpleProduct</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -474,13 +486,13 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="ApiProductWithDescriptionAndUnderscoredSku" type="product"> + <data key="name" unique="suffix">Api Simple Product</data> <data key="sku" unique="suffix">api_simple_product</data> + <data key="urlKey" unique="suffix">api-simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Simple Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-simple-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -488,26 +500,26 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="_newDefaultProduct" type="product"> + <data key="name" unique="suffix">testproductname</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">testproductname</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProductWithCustomAttributeSet" type="product"> + <data key="name" unique="suffix">testProductName</data> <data key="sku" unique="suffix">testSku</data> + <data key="urlKey" unique="suffix">testurlkey</data> <data key="type_id">simple</data> <var key="attribute_set_id" entityKey="attribute_set_id" entityType="CatalogAttributeSet"/> <data key="visibility">4</data> - <data key="name" unique="suffix">testProductName</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">testurlkey</data> <data key="status">1</data> <data key="weight">1</data> <data key="quantity">100</data> @@ -572,13 +584,13 @@ <requiredEntity type="product_option">ProductOptionFile</requiredEntity> </entity> <entity name="ApiVirtualProductWithDescription" type="product"> + <data key="name" unique="suffix">Api Virtual Product</data> <data key="sku" unique="suffix">api-virtual-product</data> + <data key="urlKey" unique="suffix">api-virtual-product</data> <data key="type_id">virtual</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Virtual Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-virtual-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -586,13 +598,13 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="ApiVirtualProductWithDescriptionAndUnderscoredSku" type="product"> + <data key="name" unique="suffix">Api Virtual Product</data> <data key="sku" unique="suffix">api_virtual_product</data> + <data key="urlKey" unique="suffix">api-virtual-product</data> <data key="type_id">virtual</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">Api Virtual Product</data> <data key="price">123.00</data> - <data key="urlKey" unique="suffix">api-virtual-product</data> <data key="status">1</data> <data key="quantity">100</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> @@ -600,15 +612,15 @@ <requiredEntity type="custom_attribute_array">ApiProductShortDescription</requiredEntity> </entity> <entity name="SimpleProductWithNewFromDate" type="product"> + <data key="name" unique="suffix">SimpleProduct</data> <data key="sku" unique="suffix">SimpleProduct</data> + <data key="urlKey" unique="suffix">simpleproduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> - <data key="name" unique="suffix">SimpleProduct</data> <data key="price">125.00</data> <data key="visibility">4</data> <data key="status">1</data> <data key="quantity">1000</data> - <data key="urlKey" unique="suffix">simpleproduct</data> <data key="weight">1</data> <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> <requiredEntity type="custom_attribute_array">ApiProductNewsFromDate</requiredEntity> @@ -635,7 +647,7 @@ <var key="sku" entityKey="sku" entityType="product3"/> </entity> <entity name="ApiSimplePrice1" type="product"> - <data key="sku" unique="suffix">api-simple-product</data> + <data key="sku" unique="suffix">apisimpleproduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> @@ -643,7 +655,7 @@ <data key="price">1.00</data> </entity> <entity name="ApiSimplePrice100" type="product"> - <data key="sku" unique="suffix">api-simple-product</data> + <data key="sku" unique="suffix">apisimpleproduct</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> @@ -756,6 +768,7 @@ <data key="status">In Stock</data> <data key="visibility">Catalog, Search</data> <data key="urlKey" unique="suffix">virtual-product</data> + <data key="storefrontStatus">IN STOCK</data> <data key="type_id">virtual</data> </entity> <entity name="virtualProductCustomImportOptions" type="product"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml index 0c88c666a20ca..c79756507794a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/TierPriceData.xml @@ -64,4 +64,12 @@ <data key="quantity">30</data> <var key="sku" entityType="product" entityKey="sku" /> </entity> -</entities> \ No newline at end of file + <entity name="tierProductPriceDiscount" type="catalogTierPrice"> + <data key="price">36.00</data> + <data key="price_type">discount</data> + <data key="website_id">0</data> + <data key="customer_group">ALL GROUPS</data> + <data key="quantity">3</data> + <var key="sku" entityType="product" entityKey="sku" /> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryBasicFieldSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryBasicFieldSection.xml index 92961cc48212a..d6017e801052b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryBasicFieldSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryBasicFieldSection.xml @@ -41,6 +41,7 @@ <element name="RequiredFieldIndicator" type="text" selector=" return window.getComputedStyle(document.querySelector('._required[data-index={{arg1}}]>.admin__field-label span'), ':after').getPropertyValue('content');" parameterized="true"/> <element name="displayMode" type="button" selector="select[name='display_mode']"/> <element name="anchor" type="checkbox" selector="input[name='is_anchor']"/> + <element name="anchorLabel" type="text" selector="input[name='is_anchor']+label"/> <element name="productListCheckBox" type="checkbox" selector="input[name='use_config[available_sort_by]']" /> <element name="productList" type="text" selector="select[name='available_sort_by']"/> <element name="defaultProductLisCheckBox" type="checkbox" selector="input[name='use_config[default_sort_by]']"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml index d89d9a5bd43c0..1627fb9512e64 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml @@ -9,10 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminCategoryProductsSection"> - <element name="sectionHeader" type="button" selector="div[data-index='assign_products']" timeout="30"/> - <element name="addProducts" type="button" selector="#catalog_category_add_product_tabs" timeout="30"/> - <element name="addProductsDisabled" type="button" selector="#catalog_category_add_product_tabs[disabled]" timeout="30"/> - <element name="productsInCategorySectionTitle" type="text" selector="div[data-index='assign_products'] .fieldset-wrapper-title" timeout="10"/> - <element name="productsInCategorySectionBody" type="text" selector="div[data-index='assign_products'] .admin__fieldset-wrapper-content"/> + <element name="sectionHeader" type="button" selector="div[data-index='assign_products'] .fieldset-wrapper-title" timeout="30"/> + <element name="sectionBody" type="button" selector="div[data-index='assign_products'] .admin__fieldset-wrapper-content" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml index 77b89a07fb76a..91ac52a91a4c4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml @@ -25,5 +25,13 @@ <element name="msrp" type="input" selector="//input[@name='product[msrp]']" timeout="30"/> <element name="msrpType" type="select" selector="//select[@name='product[msrp_display_actual_price_type]']" timeout="30"/> <element name="save" type="button" selector="#save-button" timeout="30"/> + <element name="modalTitle" type="text" selector="aside.product_form_product_form_advanced_pricing_modal h1.modal-title"/> + <!-- Last row tier price elements--> + <element name="lastTierPriceWebsite" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[website_id]']"/> + <element name="lastTierPriceCustomerGroup" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[cust_group]']"/> + <element name="lastTierPriceQty" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price_qty]']"/> + <element name="lastTierPriceType" type="select" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[value_type]']"/> + <element name="lastTierPriceFixedAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[price]']"/> + <element name="lastTierPriceDiscountAmount" type="input" selector="[data-index='tier_price'] table tbody tr.data-row:last-child [name*='[percentage_value]']"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml index 59fbeee142dfe..c51d481d7dc5e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductMessagesSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminProductMessagesSection"> - <element name="successMessage" type="text" selector=".message-success"/> + <element name="successMessage" type="text" selector=".message.message-success.success"/> <element name="errorMessage" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 9a84f90edcfc0..6b67f5609f7f0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -17,6 +17,9 @@ <element name="ProductItemInfo" type="button" selector=".product-item-info"/> <element name="specifiedProductItemInfo" type="button" selector="//a[@class='product-item-link'][contains(text(), '{{var1}}')]" parameterized="true"/> <element name="AddToCartBtn" type="button" selector="button.action.tocart.primary"/> + <element name="addToCartButtonProductInfoHover" type="button" selector=".product-item-info:hover button.action.tocart.primary" timeout="30"/> + <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist" timeout="30"/> + <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare" timeout="30"/> <element name="addToCartProductBySku" type="button" selector="//form[@data-product-sku='{{productSku}}']//button[contains(@class, 'tocart')]" parameterized="true" /> <element name="SuccessMsg" type="button" selector="div.message-success"/> <element name="productCount" type="text" selector="#toolbar-amount"/> @@ -27,6 +30,7 @@ <element name="productLink" type="text" selector="a.product-item-link" timeout="30"/> <element name="productLinkByHref" type="text" selector="a.product-item-link[href$='{{var1}}.html']" parameterized="true"/> <element name="productPrice" type="text" selector=".price-final_price"/> + <element name="productPriceByName" type="text" selector="//a[contains(text(), '{{productName}}')]//ancestor::div[contains(@class, 'product-item-info')]//span[contains(@class, 'price')]" parameterized="true"/> <element name="categoryImage" type="text" selector=".category-image"/> <element name="emptyProductMessage" type="block" selector=".message.info.empty>div"/> <element name="lineProductName" type="text" selector=".products.list.items.product-items li:nth-of-type({{line}}) .product-item-link" timeout="30" parameterized="true"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 4114d64eb39af..61e6a345b9ba5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -21,7 +21,7 @@ <element name="ProductTitleByName" type="button" selector="//main//li//a[contains(text(), '{{var1}}')]" parameterized="true"/> <element name="ProductPriceByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//span[@class='price']" parameterized="true"/> - <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'special-price')]" parameterized="true"/> + <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//div[contains(@class, 'product-item-info')][.//a[contains(text(), '{{productName}}')]]//span[@class='special-price']/span" parameterized="true"/> <element name="ProductCatalogRulePriceTitleByName" type="text" selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'price-label')]" parameterized="true"/> <element name="ProductImageByName" type="text" selector="//main//li[.//a[contains(text(), '{{var1}}')]]//img[@class='product-image-photo']" parameterized="true"/> <element name="ProductImageBySrc" type="text" selector=".products-grid img[src*='{{pattern}}']" parameterized="true"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index a5a02ad95b1f7..0b44d9bb0ea6b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -105,5 +105,7 @@ <element name="customOptionHour" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='hour']" parameterized="true"/> <element name="customOptionMinute" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='minute']" parameterized="true"/> <element name="customOptionDayPart" type="date" selector="//div[@class='field date required']//span[text()='{{option}}']/../..//div/select[@data-calendar-role='day_part']" parameterized="true"/> + + <element name="addToCartEnabled" type="button" selector="#product-addtocart-button:not([disabled])"/> </section> </sections> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 9a0f5ad002725..b34e73a7ede9f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -33,7 +33,7 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open product page--> <comment userInput="Open product page" stepKey="openProdPage"/> @@ -60,7 +60,7 @@ <waitForPageLoad stepKey="waitForProdAddToCmpList"/> <!--Assert success message--> <comment userInput="Assert success message" stepKey="assertSuccessMsg"/> - <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage"/> + <grabTextFrom selector="{{StorefrontMessagesSection.success}}" stepKey="grabTextFromSuccessMessage"/> <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage"/> <!--See product in the comparison list--> <comment userInput="See product in the comparison list" stepKey="seeProductInComparisonList"/> @@ -82,7 +82,7 @@ <waitForPageLoad stepKey="waitProdAddingToCmpList"/> <!--Assert success message--> <comment userInput="Assert success message" stepKey="assertSuccessMsg2"/> - <grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage2"/> + <grabTextFrom selector="{{StorefrontMessagesSection.success}}" stepKey="grabTextFromSuccessMessage2"/> <assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage2"/> <!--Check that product displays on add to compare widget--> <comment userInput="Check that product displays on add to compare widget" stepKey="checkProdNameOnWidget"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddToCartCrossSellTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddToCartCrossSellTest.xml index 7c0161d443df6..9abad132d32db 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddToCartCrossSellTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddToCartCrossSellTest.xml @@ -33,7 +33,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="logInAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimp1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteSimp2"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageForCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageForCategoryTest.xml index ed9eb686d2c86..690f2440b2f3b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageForCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageForCategoryTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="DeleteCategory"> <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to create a new category with image --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGCatalogTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGCatalogTest.xml index b3e6fcd3bfb55..1850faebd16c6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGCatalogTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGCatalogTest.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminAddImageToWYSIWYGCatalogTest"> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -55,7 +55,7 @@ <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGProductTest.xml index edf37542fd830..d86a696880bae 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddImageToWYSIWYGProductTest.xml @@ -18,13 +18,13 @@ <testCaseId value="MAGETWO-84375"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductCreatePage.url(AddToDefaultSet.attributeSetId, 'simple')}}" stepKey="navigateToNewProduct"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml index b98ca3a375a17..9ee5e9138d764 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml @@ -31,7 +31,7 @@ <!--Delete created entity --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product Index Page and filter the product--> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml index 4f1618e076642..bdb2293bed9bc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminApplyTierPriceToProductTest.xml @@ -33,7 +33,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex1"/> <waitForPageLoad time="30" stepKey="waitForProductIndexPageLoad"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!--Case: Group Price--> @@ -292,7 +292,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <waitForPageLoad time="30" stepKey="waitForProductIndexPageLoad"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml index 41b358bbf760e..01a1b26a1f034 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml @@ -32,7 +32,10 @@ </before> <after> <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to default attribute set edit page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogCategoriesNavigateMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogCategoriesNavigateMenuTest.xml index a51df86d0327a..03331b0d75cc5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogCategoriesNavigateMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogCategoriesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToCategoriesPage"> <argument name="menuUiId" value="{{AdminMenuCatalog.dataUiId}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogProductsNavigateMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogProductsNavigateMenuTest.xml index 1d9400bf81e4d..23c9513c7ab49 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogProductsNavigateMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCatalogProductsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToCatalogProductsPage"> <argument name="menuUiId" value="{{AdminMenuCatalog.dataUiId}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml index 95620bf75b6d0..cdb9a0a8b75d0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeProductAttributeSet.xml @@ -47,6 +47,9 @@ <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml index b4381a674827d..bc2efacfcbece 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml @@ -117,7 +117,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product in Store Front Page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml index 7c6f6ab66f63d..c9a7bae1753b4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml @@ -42,7 +42,10 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createMultiSelectProductAttribute" stepKey="deleteMultiSelectProductAttribute"/> <!-- Logout from Admin page --> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open created product for edit --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveAndNotIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveAndNotIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml index fd22142fcb097..9b95ef726a617 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveAndNotIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveAndNotIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml @@ -27,7 +27,7 @@ <after> <!--Delete created data--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveCategoryAndSubcategoryIsNotVisibleInNavigationMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveCategoryAndSubcategoryIsNotVisibleInNavigationMenuTest.xml index b6c76d6577210..3f180939bc7ea 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveCategoryAndSubcategoryIsNotVisibleInNavigationMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveCategoryAndSubcategoryIsNotVisibleInNavigationMenuTest.xml @@ -26,7 +26,7 @@ <after> <!--Delete created data--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml index c9cd9acd9708c..3edd82e060e2e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckInactiveIncludeInMenuCategoryAndSubcategoryIsNotVisibleInNavigationTest.xml @@ -27,7 +27,7 @@ <after> <!--Delete created data--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsNotVisibleInCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsNotVisibleInCategoryTest.xml index cd03d868838f3..9b7ef4077f906 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsNotVisibleInCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsNotVisibleInCategoryTest.xml @@ -31,7 +31,7 @@ <!-- Delete created entity --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product Index Page and filter the product--> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsVisibleInCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsVisibleInCategoryTest.xml index bfea4fa7557f5..433289f59f21b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsVisibleInCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckOutOfStockProductIsVisibleInCategoryTest.xml @@ -33,7 +33,7 @@ <!-- Delete created entity --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI stepKey="setDisplayOutOfStockProduct" command="config:set cataloginventory/options/show_out_of_stock 0" /> </after> <!--Open Product Index Page and filter the product--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckPaginationInStorefrontTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckPaginationInStorefrontTest.xml index 5bb9cc8a080df..c1f310575de2f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckPaginationInStorefrontTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckPaginationInStorefrontTest.xml @@ -87,7 +87,7 @@ <deleteData createDataKey="simpleProduct28" stepKey="deleteSimpleProduct28"/> <deleteData createDataKey="simpleProduct29" stepKey="deleteSimpleProduct29"/> <deleteData createDataKey="simpleProduct30" stepKey="deleteSimpleProduct30"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Verify default number of products displayed in the grid view--> <comment userInput="Verify default number of products displayed in the grid view" stepKey="commentVerifyDefaultValues"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckSubCategoryIsNotVisibleInNavigationMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckSubCategoryIsNotVisibleInNavigationMenuTest.xml index f5872ac3efca0..4ea294e3a3f36 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckSubCategoryIsNotVisibleInNavigationMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckSubCategoryIsNotVisibleInNavigationMenuTest.xml @@ -26,7 +26,7 @@ <after> <!--Delete created data--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml index cef5bc622c6cf..a213f2af900cf 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCloneProductWithDuplicateUrlTest.xml @@ -32,7 +32,7 @@ <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetFiltersIfExist"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToProductEditPage"/> <waitForPageLoad stepKey="waitForSimpleProductPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml index 80c20a7e0b5d9..2fddc667b60fd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditSimpleProductSettingsTest.xml @@ -34,7 +34,7 @@ <deleteData createDataKey="createThirdRelatedProduct" stepKey="deleteThirdRelatedProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create new simple product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditVirtualProductSettingsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditVirtualProductSettingsTest.xml index 70cbfe7259da0..43fce1cfdd329 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditVirtualProductSettingsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAndEditVirtualProductSettingsTest.xml @@ -48,7 +48,7 @@ <deleteData createDataKey="createThirdRelatedProduct" stepKey="deleteThirdRelatedProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <comment userInput="remove me" stepKey="disableWYSIWYG"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml index 51518dffaf87e..8f06565c147fa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateAttributeSetEntityTest.xml @@ -26,6 +26,9 @@ <after> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml index 784b5d3fd1827..44a83f2dbadd4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml @@ -19,7 +19,7 @@ <group value="category"/> </annotations> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> @@ -52,7 +52,7 @@ </before> <after> <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> @@ -83,7 +83,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithAnchorFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithAnchorFieldTest.xml index 7de1d38f097c5..8900e85ca3431 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithAnchorFieldTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithAnchorFieldTest.xml @@ -24,7 +24,7 @@ </before> <after> <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createDefaultCMSBlock" stepKey="deleteDefaultCMSBlock"/> <deleteData stepKey="deleteSimpleProduct" createDataKey="simpleProduct"/> </after> @@ -64,6 +64,14 @@ <waitForPageLoad stepKey="waitForPageTitleToBeSaved"/> <!--Verify the Category Title--> <see selector="{{AdminCategoryContentSection.categoryPageTitle}}" userInput="{{_defaultCategory.name}}" stepKey="seePageTitle" /> + <grabFromCurrentUrl stepKey="categoryId" regex="#\/([0-9]*)?\/$#"/> + <!-- Assert Redirect path, Target Path and Redirect type in grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath"> + <argument name="redirectPath" value="{{_defaultCategory.name}}.html" /> + <argument name="redirectType" value="No" /> + <argument name="targetPath" value="catalog/category/view/id/{$categoryId}"/> + </actionGroup> + <!--Clear cache and reindex--> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithCustomRootCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithCustomRootCategoryTest.xml index a68a585bbf31d..ac237fbe49978 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithCustomRootCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithCustomRootCategoryTest.xml @@ -29,7 +29,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCreatedNewRootCategory"> <argument name="categoryEntity" value="NewRootCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> <waitForPageLoad stepKey="waitForCategoryIndexPageToBeLoaded"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithFiveNestingTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithFiveNestingTest.xml index 530bafaef24c2..bc60f21b5d214 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithFiveNestingTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithFiveNestingTest.xml @@ -33,7 +33,7 @@ <see selector="You deleted the category." stepKey="seeDeleteSuccess"/> <click selector="{{AdminCategorySidebarTreeSection.expandAll}}" stepKey="expandToSeeAllCategories"/> <dontSee selector="{{AdminCategorySidebarTreeSection.categoryInTree(FirstLevelSubCat.name)}}" stepKey="dontSeeCategoryInTree"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create Category with Five Nesting --> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveCategoryTest.xml index fae1a1fa8c2e4..ca2b15658f02e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveCategoryTest.xml @@ -22,7 +22,7 @@ </before> <after> <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create In active Category --> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveIncludeInMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveIncludeInMenuTest.xml index a695aa33079bd..f6b0a0a321c5d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveIncludeInMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithInactiveIncludeInMenuTest.xml @@ -22,7 +22,7 @@ </before> <after> <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create Category with not included in menu Subcategory --> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithNoAnchorFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithNoAnchorFieldTest.xml new file mode 100644 index 0000000000000..5342dec6b1ebb --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithNoAnchorFieldTest.xml @@ -0,0 +1,93 @@ +<?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="AdminCreateCategoryWithNoAnchorFieldTest"> + <annotations> + <stories value="Create categories"/> + <title value="Create no anchor subcategory with all fields"/> + <description value="Login as admin and create no anchor subcategory with all fields"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="Catalog"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="_defaultBlock" stepKey="createDefaultCMSBlock"/> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct" /> + </before> + <after> + <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + <deleteData createDataKey="createDefaultCMSBlock" stepKey="deleteDefaultCMSBlock"/> + <deleteData stepKey="deleteSimpleProduct" createDataKey="simpleProduct"/> + </after> + + <!--Create SubCategory--> + <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> + <waitForPageLoad stepKey="waitForPageToLoaded"/> + <click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategoryButton"/> + <fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{_defaultCategory.name}}" stepKey="fillCategoryName"/> + <checkOption selector="{{AdminCategoryBasicFieldSection.EnableCategory}}" stepKey="enableCategory"/> + + <!--Select Content and fill the options--> + <scrollTo selector="{{AdminCategoryContentSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToContent"/> + <click selector="{{AdminCategoryContentSection.sectionHeader}}" stepKey="selectContent"/> + <scrollTo selector="{{AdminCategoryContentSection.AddCMSBlock}}" x="0" y="-80" stepKey="scrollToAddCMSBlock"/> + <selectOption selector="{{AdminCategoryContentSection.AddCMSBlock}}" userInput="$$createDefaultCMSBlock.title$$" stepKey="selectCMSBlock"/> + + <!--Select Display Setting and fill the options--> + <scrollTo selector="{{CategoryDisplaySettingsSection.DisplaySettingTab}}" x="0" y="-80" stepKey="scrollToDisplaySetting"/> + <click selector="{{CategoryDisplaySettingsSection.DisplaySettingTab}}" stepKey="selectDisplaySetting"/> + <selectOption selector="{{CategoryDisplaySettingsSection.displayMode}}" userInput="PRODUCTS_AND_PAGE" stepKey="selectdisplayMode"/> + <click selector="{{CategoryDisplaySettingsSection.anchorLabel}}" stepKey="uncheckAnchor"/> + <click selector="{{CategoryDisplaySettingsSection.productListCheckBox}}" stepKey="enableTheAvailableProductList"/> + <selectOption selector="{{CategoryDisplaySettingsSection.productList}}" parameterArray="['Position', 'Product Name', 'Price']" stepKey="selectPrice"/> + <scrollTo selector="{{CategoryDisplaySettingsSection.defaultProductLisCheckBox}}" x="0" y="-80" stepKey="scrollToDefaultProductList"/> + <click selector="{{CategoryDisplaySettingsSection.defaultProductLisCheckBox}}" stepKey="enableTheDefaultProductList"/> + <selectOption selector="{{CategoryDisplaySettingsSection.defaultProductList}}" userInput="name" stepKey="selectProductName"/> + <scrollTo selector="{{CategoryDisplaySettingsSection.layeredNavigationPriceCheckBox}}" x="0" y="-80" stepKey="scrollToLayeredNavPrice"/> + <click selector="{{CategoryDisplaySettingsSection.layeredNavigationPriceCheckBox}}" stepKey="enableLayeredNavigationPrice"/> + <fillField selector="{{CategoryDisplaySettingsSection.layeredNavigationPriceInput}}" userInput="5.5" stepKey="fillThePrice"/> + + <!--Search the products and select the category products--> + <actionGroup ref="AdminAddProductToCategoryActionGroup" stepKey="addProductToCategory"> + <argument name="product" value="$$simpleProduct$$"/> + </actionGroup> + <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="clickSaveButton"/> + <waitForPageLoad stepKey="waitForCategorySaved"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the category." stepKey="assertSuccessMessage"/> + <waitForPageLoad stepKey="waitForPageTitleToBeSaved"/> + + <!-- Get Category ID --> + <actionGroup ref="OpenCategoryFromCategoryTreeActionGroup" stepKey="getCategoryId"> + <argument name="category" value="{{_defaultCategory.name}}"/> + </actionGroup> + <grabFromCurrentUrl stepKey="categoryId" regex="#\/([0-9]*)?\/$#"/> + + <!--Verify the Category Title--> + <see selector="{{AdminCategoryContentSection.categoryPageTitle}}" userInput="{{_defaultCategory.name}}" stepKey="seePageTitle" /> + + <!--Verify Url Rewrite--> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath"> + <argument name="redirectPath" value="{{_defaultCategory.name_lwr}}.html"/> + <argument name="redirectType" value="No"/> + <argument name="targetPath" value="catalog/category/view/id/{$categoryId}"/> + </actionGroup> + + <!--Verify Product in store front page--> + <amOnPage url="{{StorefrontCategoryPage.url(_defaultCategory.name_lwr)}}" stepKey="amOnCategoryPage"/> + <waitForPageLoad stepKey="waitForPageToBeLoaded"/> + <see selector="{{StorefrontCategoryMainSection.CategoryTitle}}" userInput="{{_defaultCategory.name}}" stepKey="seeCategoryPageTitle"/> + <seeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName(_defaultCategory.name)}}" stepKey="seeCategoryOnNavigation"/> + <waitForPageLoad stepKey="waitForProductToLoad"/> + <seeElement selector="{{StorefrontCategoryMainSection.productLinkByHref($$simpleProduct.urlKey$$)}}" stepKey="seeProductInCategory"/> + <dontSeeElement selector="{{StorefrontCategorySidebarSection.filterOptions}}" stepKey="dontSeeFilterOptionsForNonAnchorCategory"/> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithProductsGridFilter.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithProductsGridFilter.xml index 6a49b47b75078..2a4718223ef0c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithProductsGridFilter.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithProductsGridFilter.xml @@ -29,7 +29,7 @@ <argument name="product" value="SimpleProduct"/> </actionGroup> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="NavigateToAndResetProductGridToDefaultView"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductList"/> <waitForPageLoad stepKey="waitForProductList"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithRequiredFieldsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithRequiredFieldsTest.xml index dac2a121d107f..110f52aaeb40a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithRequiredFieldsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryWithRequiredFieldsTest.xml @@ -22,7 +22,7 @@ </before> <after> <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create subcategory with required fields --> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCustomProductAttributeWithDropdownFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCustomProductAttributeWithDropdownFieldTest.xml index 2d1a58764e20a..2b33f4a6bb1c0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCustomProductAttributeWithDropdownFieldTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCustomProductAttributeWithDropdownFieldTest.xml @@ -42,7 +42,7 @@ <argument name="ProductAttribute" value="newProductAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml index 981af5b5abb4a..e32aad76c9b28 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDatetimeProductAttributeTest.xml @@ -24,7 +24,7 @@ <argument name="ProductAttribute" value="DatetimeProductAttribute"/> </actionGroup> <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="resetGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Generate the datetime default value --> <generateDate date="now" format="n/j/y g:i A" stepKey="generateDefaultValue"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeTest.xml index 4118356b07e74..4b69123635852 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="DeleteProductAttributeActionGroup" stepKey="deleteAttribute"> <argument name="ProductAttribute" value="productDropDownAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductAttributePage.url}}" stepKey="navigateToNewProductAttributePage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 557f0768c98a3..b36cbc27f7086 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -34,7 +34,12 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <deleteData createDataKey="attribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Filter product attribute set by attribute set name --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateCategoryTest.xml index cbef9566b2b78..4c91c6bac0e1a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateCategoryTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Category Page and select Add category --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml index 3eb617d19d54c..c6703a1109345 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml @@ -29,7 +29,7 @@ <after> <deleteData createDataKey="subCategory" stepKey="deleteSubCategory"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to new simple product page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryAndUpdateAsInactiveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryAndUpdateAsInactiveTest.xml index b0e6fe87be918..bff43cf65faf6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryAndUpdateAsInactiveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryAndUpdateAsInactiveTest.xml @@ -52,7 +52,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewFr"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Select created category and make category inactive--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryTest.xml index 7de37b9cb77ef..9ef3659cb5ab1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveFlatCategoryTest.xml @@ -52,7 +52,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewFr"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Select created category and make category inactive--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveInMenuFlatCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveInMenuFlatCategoryTest.xml index c7aba1fe8376f..4623f9ad4005b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveInMenuFlatCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateInactiveInMenuFlatCategoryTest.xml @@ -52,7 +52,7 @@ <argument name="customStore" value="customStoreFR"/> </actionGroup> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Select created category and disable Include In Menu option--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 6bfd012bc88b2..2c8ec9ad7d1b9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -40,7 +40,10 @@ <!-- Delete product attribute set --> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Filter product attribute set by attribute set name --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductPageTest.xml index 51c4a3250d609..4ffb81d9a1d67 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductPageTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="GoToProductCatalogPageActionGroup" stepKey="goToProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml index 8fb226f5f5585..a39bc0bd39e2f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewAttributeFromProductTest.xml @@ -42,7 +42,7 @@ <argument name="ProductAttribute" value="productDropDownAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create 2 store views--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml index a105f343d3e21..f468f61fada04 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml @@ -27,7 +27,11 @@ </before> <after> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Navigate to Stores > Attributes > Attribute Set --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml index 2e502f58041e6..18d1ec5b30f72 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml @@ -39,7 +39,7 @@ <argument name="ProductAttribute" value="newProductAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeRequiredTextFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeRequiredTextFieldTest.xml index 63eed37b1e84f..a6632fa1ddabb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeRequiredTextFieldTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeRequiredTextFieldTest.xml @@ -37,7 +37,7 @@ <actionGroup ref="DeleteProductAttributeActionGroup" stepKey="deleteCreatedAttribute"> <argument name="ProductAttribute" value="newProductAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductDuplicateUrlkeyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductDuplicateUrlkeyTest.xml index eacb69db38e9a..ecce1bb1517e1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductDuplicateUrlkeyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductDuplicateUrlkeyTest.xml @@ -23,7 +23,7 @@ </createData> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> </after> @@ -62,7 +62,7 @@ <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> <deleteData createDataKey="createCategory" stepKey="deletePreReqCatalog" /> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct1"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryAndSubcategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryAndSubcategoriesTest.xml index 7a99750c00e53..2352e231e66a4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryAndSubcategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryAndSubcategoriesTest.xml @@ -36,7 +36,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCreatedNewRootCategory"> <argument name="categoryEntity" value="NewRootCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout2"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout2"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="amOnAdminCategoryPage"/> @@ -70,7 +70,7 @@ <selectOption userInput="{{NewRootCategory.name}}" selector="{{AdminNewStoreGroupSection.storeRootCategoryDropdown}}" stepKey="selectOptionCreatedNewRootCategory"/> <click selector="{{AdminStoreGroupActionsSection.saveButton}}" stepKey="clickSaveStoreButton"/> <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="clickOkOnModalDialog1"/> - <actionGroup ref="logout" stepKey="logout1"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout1"/> <!--Go to storefront and verify created subcategory on frontend--> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefrontPage"/> <waitForPageLoad stepKey="waitForPageAdminSystemStoreLoad2"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryRequiredFieldsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryRequiredFieldsTest.xml index 2b824554b9bd4..a5556b076fef6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryRequiredFieldsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateRootCategoryRequiredFieldsTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> <argument name="categoryEntity" value="_defaultCategory" /> </actionGroup> - <actionGroup ref="logout" stepKey="logout" /> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout" /> </after> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="OpenAdminCatergoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductNotVisibleIndividuallyTest.xml new file mode 100644 index 0000000000000..4188fc628064a --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductNotVisibleIndividuallyTest.xml @@ -0,0 +1,46 @@ +<?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="AdminCreateSimpleProductNotVisibleIndividuallyTest"> + <annotations> + <features value="Catalog"/> + <stories value="Create a Simple Product via Admin"/> + <title value="Create Simple Product that Not Visible Individually"/> + <description value="Create Simple Product that Not Visible Individually"/> + <severity value="CRITICAL"/> + <testCaseId value=""/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + </before> + <after> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> + </after> + + <!--Create Simple Product Not Visible Individually--> + <actionGroup ref="FillAdminSimpleProductFormActionGroup" stepKey="fillProductFieldsInAdmin"> + <argument name="category" value="$$createPreReqCategory$$"/> + <argument name="simpleProduct" value="simpleProductNotVisibleIndividually"/> + </actionGroup> + + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchUrlRewriteForNotVisibleProductInGrid"> + <argument name="requestPath" value="{{simpleProductNotVisibleIndividually.urlKey}}.html"/> + </actionGroup> + + <!--Verify AssertPageByUrlRewriteIsNotFound--> + <actionGroup ref="AssertPageByUrlRewriteIsNotFoundActionGroup" stepKey="amOnPage"> + <argument name="requestPath" value="{{simpleProductNotVisibleIndividually.urlKey}}.html"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductTest.xml index 052f6b1924e89..1c6ed551d3f72 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductTest.xml @@ -30,6 +30,7 @@ <argument name="category" value="$$createPreReqCategory$$"/> <argument name="simpleProduct" value="_defaultProduct"/> </actionGroup> + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> <actionGroup ref="AssertProductInStorefrontCategoryPage" stepKey="assertProductInStorefront1"> <argument name="category" value="$$createPreReqCategory$$"/> <argument name="product" value="_defaultProduct"/> @@ -54,7 +55,7 @@ </before> <after> <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithCountryOfManufactureAttributeSKUMaskTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithCountryOfManufactureAttributeSKUMaskTest.xml index bbaabffcc5ecd..967babc617ce9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithCountryOfManufactureAttributeSKUMaskTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithCountryOfManufactureAttributeSKUMaskTest.xml @@ -28,7 +28,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{nameAndAttributeSkuMaskSimpleProduct.name}}-{{nameAndAttributeSkuMaskSimpleProduct.country_of_manufacture_label}}" /> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="openProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithDatetimeAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithDatetimeAttributeTest.xml index 0f88fa9d6abf4..fe5b70b8e4ca7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithDatetimeAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithDatetimeAttributeTest.xml @@ -27,7 +27,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnProductIndexPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Generate default value --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithUnicodeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithUnicodeTest.xml index 5dcc23a725b84..9660a46d43dba 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithUnicodeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateSimpleProductWithUnicodeTest.xml @@ -22,7 +22,7 @@ <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> </after> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateTextEditorProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateTextEditorProductAttributeTest.xml index 848e765d34d70..bad620b3dab99 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateTextEditorProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateTextEditorProductAttributeTest.xml @@ -40,7 +40,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Stores > Product, click "Add New Attribute" --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductFillingRequiredFieldsOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductFillingRequiredFieldsOnlyTest.xml index c3fe666c84fd4..6d39455e4a31b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductFillingRequiredFieldsOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductFillingRequiredFieldsOnlyTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml index 9db9f64396826..df46983b361c6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductOutOfStockWithTierPriceTest.xml @@ -28,7 +28,7 @@ <argument name="sku" value="{{virtualProductOutOfStock.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml index fe39bb6ada2bd..899f3af02c78e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml @@ -28,7 +28,7 @@ <argument name="sku" value="{{virtualProductCustomImportOptions.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetOrderFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index 4c3d519106389..84cba791c6629 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateVirtualProductWithTierPriceForGeneralGroupTest"> <annotations> + <features value="Catalog"/> <stories value="Create virtual product"/> <title value="Create virtual product with tier price for General group"/> <description value="Test log in to Create virtual product and Create virtual product with tier price for General group"/> @@ -17,122 +18,96 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30682"/> - </skip> </annotations> <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> <createData entity="Simple_US_CA_Customer" stepKey="customer" /> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> + <deleteData createDataKey="categoryEntity" stepKey="deleteSimpleSubCategory"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <deleteData stepKey="deleteCustomer" createDataKey="customer"/> - <actionGroup ref="logout" stepKey="logout"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppears"/> + <see selector="{{AdminMessagesSection.success}}" userInput="A total of 1 record(s) have been deleted." stepKey="seeSuccessMessage"/> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearFiltersAfter"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> - <waitForPageLoad stepKey="waitForProductCatalogPage"/> - <click selector="{{AdminProductGridActionSection.addProductToggle}}" stepKey="clickAddProductToggle"/> - <waitForPageLoad stepKey="waitForProductToggleToSelectProduct"/> - <click selector="{{AdminProductGridActionSection.addVirtualProduct}}" stepKey="clickVirtualProduct"/> - - <!-- Create virtual product with tier price for general group --> - <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillProductName"/> - <fillField selector="{{AdminProductFormSection.productSku}}" userInput="{{virtualProductGeneralGroup.sku}}" stepKey="fillProductSku"/> - <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{virtualProductGeneralGroup.price}}" stepKey="fillProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.website}}" stepKey="selectProductTierPriceWebsite"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.customer_group}}" stepKey="selectProductTierPriceGroup"/> - <scrollTo selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" x="50" y="0" stepKey="scrollToProductTierPriceQuantityInputTextBox"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnGeneralGroup.qty}}" stepKey="fillProductTierPriceQuantityInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnGeneralGroup.price}}" stepKey="fillProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + <!-- Create virtual product--> + <amOnPage url="{{AdminProductCreatePage.url(AddToDefaultSet.attributeSetId,'virtual')}}" stepKey="openVirtualProductCreatePage"/> + <actionGroup ref="FillMainProductFormNoWeightActionGroup" stepKey="fillNewProductData"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialog"/> + <actionGroup ref="AdminProductFormAdvancedPricingAddTierPriceActionGroup" stepKey="addTierPrice"> + <argument name="website" value="{{tierPriceOnGeneralGroup.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnGeneralGroup.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnGeneralGroup.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductTaxClass"/> - <fillField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{virtualProductGeneralGroup.quantity}}" stepKey="fillProductQuantity"/> - <click selector="{{AdminProductFormSection.productStockStatus}}" stepKey="clickProductStockStatus"/> - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> - <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> + <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> + <argument name="categoryName" value="$categoryEntity.name$"/> + </actionGroup> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{virtualProductGeneralGroup.visibility}}" stepKey="selectVisibility"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSectionHeader"/> - <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{virtualProductGeneralGroup.urlKey}}" stepKey="fillUrlKeyInput"/> - <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> - <click selector="{{AdminProductFormSection.save}}" stepKey="clickSaveButton"/> - <waitForPageLoad stepKey="waitForVirtualProductSaved"/> - - <!-- Verify we see success message --> - <see selector="{{AdminProductFormSection.successMessage}}" userInput="You saved the product." stepKey="seeAssertVirtualProductSuccessMessage"/> + <actionGroup ref="SetProductUrlKeyByStringActionGroup" stepKey="updateUrlKey"> + <argument name="urlKey" value="{{virtualProductGeneralGroup.urlKey}}"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage1"/> - <waitForPageLoad stepKey="waitForProductCatalogPage1"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="checkRetailCustomerTaxClass" /> - <fillField selector="{{AdminProductGridFilterSection.keywordSearch}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillVirtualProductName"/> - <click selector="{{AdminProductGridFilterSection.keywordSearchButton}}" stepKey="clickKeywordSearchButton"/> - <waitForPageLoad stepKey="waitForProductSearch"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyCreatedVirtualProduct"/> - <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <!-- Search created virtual product(from above steps) in the grid --> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForVirtualProduct"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> - <!-- Verify we see created virtual product with tier price for general group(from the above step) in the product form page --> - <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeProductName"/> - <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{virtualProductGeneralGroup.sku}}" stepKey="seeProductSku"/> - <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{virtualProductGeneralGroup.price}}" stepKey="seeProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink1"/> - <seeOptionIsSelected selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.website}}" stepKey="seeProductTierPriceWebsite"/> - <seeOptionIsSelected selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnGeneralGroup.customer_group}}" stepKey="seeProductTierPriceGroup"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnGeneralGroup.qty}}" stepKey="seeProductTierPriceQuantityInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnGeneralGroup.price}}" stepKey="seeProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickAdvancedPricingCloseButton"/> + <!-- Verify customer see created virtual product with tier price in the product form page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="verifyProductInAdminEditForm"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialogAgain"/> + <actionGroup ref="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup" stepKey="checkTierPrice"> + <argument name="rowNumber" value="0"/> + <argument name="website" value="{{tierPriceOnGeneralGroup.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnGeneralGroup.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnGeneralGroup.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormCloseAdvancedPricingDialogActionGroup" stepKey="closeAdvancedPricingModal"/> <seeInField selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="seeProductTaxClass"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{virtualProductGeneralGroup.quantity}}" stepKey="seeProductQuantity"/> - <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{virtualProductGeneralGroup.status}}" stepKey="seeProductStockStatus"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories" /> + <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories"/> <assertEquals stepKey="assertSelectedCategories"> <actualResult type="variable">selectedCategories</actualResult> - <expectedResult type="array">[$$categoryEntity.name$$]</expectedResult> + <expectedResult type="array">[$categoryEntity.name$]</expectedResult> </assertEquals> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneOnCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{virtualProductGeneralGroup.visibility}}" stepKey="seeVisibility"/> - <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.useDefaultUrl}}" visible="false" stepKey="openSearchEngineOptimizationSection"/> + <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="scrollToAdminProductSEOSection"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{virtualProductGeneralGroup.urlKey}}" stepKey="seeUrlKey"/> - <!--Verify customer see created virtual product on category page --> - <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageToLoad"/> - <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeVirtualProductNameOnCategoryPage"/> + <!--Verify customer see created virtual product link on category page --> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="openCategoryPageOnFrontend"> + <argument name="category" value="$categoryEntity$"/> + </actionGroup> + <actionGroup ref="AssertProductOnCategoryPageActionGroup" stepKey="checkProductOnCategoryPage"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> - <!-- Verify customer see created virtual product with tier price for general group(from above step) in storefront page with customer --> + <!--Verify customer see updated virtual product with tier price on product storefront page --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> - <argument name="Customer" value="$$customer$$" /> + <argument name="Customer" value="$customer$" /> </actionGroup> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToStorefront"/> - <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="fillVirtualProductNameInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{virtualProductGeneralGroup.name}}" stepKey="seeVirtualProductName"/> - <grabTextFrom selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" stepKey="tierPriceTextOnStorefrontPage"/> - - <!-- Verify customer see created virtual product with tier price --> - <assertEquals stepKey="assertTierPriceTextOnCategoryPage"> - <expectedResult type="string">As low as ${{tierPriceOnGeneralGroup.price}}</expectedResult> - <actualResult type="variable">tierPriceTextOnStorefrontPage</actualResult> - </assertEquals> - <click selector="{{StorefrontQuickSearchResultsSection.productLink}}" stepKey="openSearchedProduct"/> - <waitForPageLoad stepKey="waitForProductPageToBeLoaded"/> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierPriceOnGeneralGroup.qty}} for ${{tierPriceOnGeneralGroup.price}} each and save 20%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertProductInStorefrontProductPageActionGroup" stepKey="verifyProductOnFrontend"> + <argument name="product" value="virtualProductGeneralGroup"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="{{virtualProductGeneralGroup.storefrontStatus}}" stepKey="assertStockAvailableOnProductPage"/> + <see selector="{{StorefrontProductInfoMainSection.tierPriceText}}" userInput="Buy {{tierPriceOnGeneralGroup.qty}} for ${{tierPriceOnGeneralGroup.price}} each and save 20%" stepKey="assertTierPriceTextOnProductPage"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml index 40f26761e7b6d..ea73de1cab15d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml index cb41b0292d33a..685db6db90a10 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithoutManageStockTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml index 973ff0381584a..bb4ff7acaa4a7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml @@ -28,7 +28,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSetsPage"/> <fillField selector="{{AdminProductAttributeSetGridSection.filter}}" userInput="$$createAttributeSet.attribute_set_name$$" stepKey="filterByAttributeName"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml index 4a305b8dfec75..3510b99a0c778 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml @@ -81,7 +81,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product in Store Front Page --> <amOnPage url="$$createConfigProduct.sku$$.html" stepKey="openProductInStoreFront"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml index 3abe68a503b57..373d14d4d0db4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml @@ -28,7 +28,10 @@ <after> <!--Delete Created Data --> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Attribute Set Page --> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml index 4060182a9bace..de95604e76a2f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml @@ -22,7 +22,10 @@ <createData entity="productAttributeWysiwyg" stepKey="createProductAttribute"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openProductAttributeFromSearchResultInGrid"> <argument name="productAttributeCode" value="$$createProductAttribute.attribute_code$$"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductWithCustomOptionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductWithCustomOptionTest.xml index dec911ec84a8d..834da3f4d4f9b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductWithCustomOptionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductWithCustomOptionTest.xml @@ -28,7 +28,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteSimpleProductFilteredBySkuAndName"> <argument name="product" value="$$createSimpleProduct$$"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductsImageInCaseOfMultipleStoresTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductsImageInCaseOfMultipleStoresTest.xml index 55c98bcc13d34..9ed0a8104faa1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductsImageInCaseOfMultipleStoresTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductsImageInCaseOfMultipleStoresTest.xml @@ -67,7 +67,7 @@ <deleteData createDataKey="createRootCategory" stepKey="deleteRootCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <createData entity="DefaultWebUrlOptionsConfig" stepKey="defaultWebUrlOptionsConfig"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Grab new store view code--> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="navigateToNewWebsitePage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryAssignedToStoreTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryAssignedToStoreTest.xml index e4b269dff96ba..77ebf77f05e58 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryAssignedToStoreTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryAssignedToStoreTest.xml @@ -26,7 +26,7 @@ <argument name="storeGroupName" value="customStore.code"/> </actionGroup> <deleteData createDataKey="rootCategory" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="amOnAdminSystemStorePage"/> @@ -48,4 +48,4 @@ <!--Verify Delete button is not displayed--> <dontSeeElement selector="{{AdminCategoryMainActionsSection.DeleteButton}}" stepKey="dontSeeDeleteButton"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryTest.xml index e7ab14c77945a..5e9e536203f1e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootCategoryTest.xml @@ -22,7 +22,7 @@ <createData entity="NewRootCategory" stepKey="rootCategory" /> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Verify Created root Category--> @@ -41,4 +41,4 @@ <click selector="{{AdminCategorySidebarTreeSection.expandAll}}" stepKey="expandToSeeAllCategories1"/> <dontSee selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{NewRootCategory.name}}" stepKey="dontSeeRootCategory"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootSubCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootSubCategoryTest.xml index 6df571f403ac9..48422d9ba2025 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootSubCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteRootSubCategoryTest.xml @@ -29,7 +29,7 @@ <argument name="storeGroupName" value="customStore.code"/> </actionGroup> <deleteData createDataKey="rootCategory" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create a Store--> @@ -83,8 +83,10 @@ <!--Verify in Category is not in Url Rewrite grid--> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteIndexPage"/> <waitForPageLoad stepKey="waitForUrlRewritePageTopLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SimpleRootSubCategory.url_key}}" stepKey="fillRequestPath"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> - <see selector="{{AdminUrlRewriteIndexSection.emptyRecordMessage}}" userInput="We couldn't find any records." stepKey="seeEmptyRow"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SimpleRootSubCategory.url_key}}" stepKey="fillRequestPath"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="seeEmptyRow"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSimpleProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSimpleProductTest.xml index 5b8ac5157514d..5c8b90a26594b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSimpleProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSimpleProductTest.xml @@ -27,7 +27,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteSimpleProductFilteredBySkuAndName"> <argument name="product" value="$$createSimpleProduct$$"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSystemProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSystemProductAttributeTest.xml index 6de1a5cd359cd..c3a550165de89 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSystemProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteSystemProductAttributeTest.xml @@ -21,7 +21,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttribute"/> <waitForPageLoad stepKey="waitForPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index 4f05c364fda0e..8528212e8fa20 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -31,7 +31,10 @@ <after> <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Attribute Set Page --> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="goToAttributeSets"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteVirtualProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteVirtualProductTest.xml index 86f253f358532..642fb1c1f7ba0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteVirtualProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteVirtualProductTest.xml @@ -27,7 +27,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProductFilteredBySkuAndName"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDisableProductOnChangingAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDisableProductOnChangingAttributeSetTest.xml index 0fc2c022b81e9..8ce478ff48469 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDisableProductOnChangingAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDisableProductOnChangingAttributeSetTest.xml @@ -29,7 +29,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="login"/> <amOnPage url="{{AdminProductAttributeSetEditPage.url}}/$$createAttributeSet.attribute_set_id$$/" stepKey="onAttributeSetEdit"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml index feea0930390b7..30b06ac8e0b43 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MC-6215"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> <createData stepKey="myProductAttributeCreation" entity="productAttributeWysiwyg"/> @@ -76,7 +76,7 @@ <after> <deleteData createDataKey="myProductAttributeCreation" stepKey="deletePreReqProductAttribute" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml index 0b230b0b8e002..5ad3ee6f83e2d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilterByNameByStoreViewOnProductGridTest.xml @@ -26,7 +26,7 @@ <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToEditPage"/> <actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToDefaultStoreView"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml index 77b719c03091e..a6f34af9f5315 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminFilteringCategoryProductsUsingScopeSelectorTest.xml @@ -97,7 +97,7 @@ <deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/> <deleteData createDataKey="createProduct12" stepKey="deleteProduct3"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Step 1-2: Open Category page and Set scope selector to All Store Views--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="goToCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml index 81d032850bf5a..a42fe576751f7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminGridPageNumberAfterSaveAndCloseActionTest.xml @@ -47,7 +47,7 @@ <deleteData stepKey="deleteProduct1" createDataKey="product1"/> <deleteData stepKey="deleteCategory2" createDataKey="category2"/> <deleteData stepKey="deleteProduct2" createDataKey="product2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductCatalogPage.url}}" stepKey="goToProductCatalog"/> <waitForPageLoad stepKey="waitForProductIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml index 76c0d7f7b931c..cfce9143f6cc6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminImportCustomizableOptionToProductWithSKUTest.xml @@ -46,7 +46,7 @@ <argument name="sku" value="$$createFirstProduct.sku$$-1"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductGridFilter"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Change second product sku to first product sku--> <amOnPage url="{{AdminProductEditPage.url($$createSecondProduct.id$$)}}" stepKey="goToProductEditPage1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index e98b145f01401..f803050b7a59b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -26,7 +26,7 @@ <after> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductAttributesGlobalScopeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductAttributesGlobalScopeTest.xml index 71873fe5b0960..0fbbca2602e86 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductAttributesGlobalScopeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductAttributesGlobalScopeTest.xml @@ -38,7 +38,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="AdminDeleteStoreViewActionGroup"/> <click selector="{{AdminStoresGridSection.resetButton}}" stepKey="resetSearchFilter"/> <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductFilter"/> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <!-- Search and select products --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductStatusStoreViewScopeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductStatusStoreViewScopeTest.xml index 21c6c56adfd96..6030e76dca721 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductStatusStoreViewScopeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassUpdateProductStatusStoreViewScopeTest.xml @@ -21,7 +21,7 @@ <group value="SearchEngineElasticsearch"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <!--Create Website --> <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createAdditionalWebsite"> @@ -80,7 +80,7 @@ <actionGroup ref="DeleteProductActionGroup" stepKey="deleteProduct2"> <argument name="productName" value="simpleProductForMassUpdate2.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <!-- Search and select products --> @@ -171,7 +171,7 @@ <group value="SearchEngineMysql"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <!--Create Website --> <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createAdditionalWebsite"> @@ -230,7 +230,7 @@ <actionGroup ref="DeleteProductActionGroup" stepKey="deleteProduct2"> <argument name="productName" value="simpleProductForMassUpdate2.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <!-- Search and select products --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index f178d55b97fca..72ef78accb7fc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -14,11 +14,9 @@ <title value="Admin should be able to move a category via categories tree and changes should be applied on frontend without a forced cache cleaning"/> <description value="Admin should be able to move a category via categories tree and changes should be applied on frontend without a forced cache cleaning"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-76273"/> + <testCaseId value="MC-10022"/> + <useCaseId value="MAGETWO-89248"/> <group value="category"/> - <skip> - <issueId value="MC-30720"/> - </skip> </annotations> <before> <createData entity="SimpleSubCategory" stepKey="simpleSubCategoryOne"/> @@ -32,95 +30,102 @@ <createData entity="_defaultProduct" stepKey="productTwo"> <requiredEntity createDataKey="simpleSubCategoryOne"/> </createData> - <magentoCLI command="cron:run --group=index" stepKey="runIndexerCron"/> + + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="firstRunToScheduleJobs"/> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="secondRunToExecuteJobs"/> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> + <after> - <actionGroup ref="logout" stepKey="logoutAdminUserAfterTest"/> <deleteData createDataKey="productOne" stepKey="deleteProductOne"/> <deleteData createDataKey="productTwo" stepKey="deleteProductTwo"/> <deleteData createDataKey="simpleSubCategoryWithParent" stepKey="deleteSubcategoryWithParent"/> + <deleteData createDataKey="simpleSubCategoryOne" stepKey="deleteSubcategoryOne"/> <deleteData createDataKey="simpleSubCategoryTwo" stepKey="deleteSubcategoryTwo"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdminUserAfterTest"/> </after> + <!--Move category one to category two--> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToAdminCategoryPage"/> <waitForPageLoad stepKey="waitForAdminCategoryPageLoad1"/> <actionGroup ref="MoveCategoryActionGroup" stepKey="moveSimpleSubCategoryOneToSimpleSubCategoryTwo"> - <argument name="childCategory" value="$$simpleSubCategoryOne.name$$"/> - <argument name="parentCategory" value="$$simpleSubCategoryTwo.name$$"/> + <argument name="childCategory" value="$simpleSubCategoryOne.name$"/> + <argument name="parentCategory" value="$simpleSubCategoryTwo.name$"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="/" stepKey="amOnStorefrontPage1"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage1"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened1"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="verifyThatTopCategoryIsSubCategoryTwo"/> - <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="mouseOverSubCategoryTwo"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatTopCategoryIsSubCategoryTwo"/> + <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="mouseOverSubCategoryTwo"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverSubCategoryTwo"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="verifyThatFirstLevelIsSubCategoryOne"/> - <moveMouseOver selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="mouseOverSubCategoryOne"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="verifyThatFirstLevelIsSubCategoryOne"/> + <moveMouseOver selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="mouseOverSubCategoryOne"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverSubCategoryOne"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryWithParent.name$$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent1"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryWithParent.name$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent1"/> <!--Open category one via navigation menu. Verify that subcategory is shown in layered navigation--> - <click selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryOne.name$$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu1"/> + <click selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryOne.name$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu1"/> <actionGroup ref="CheckItemInLayeredNavigationActionGroup" stepKey="verifySimpleSubCategoryWithParentInLayeredNavigation1"> <argument name="itemType" value="Category"/> - <argument name="itemName" value="$$simpleSubCategoryWithParent.name$$"/> + <argument name="itemName" value="$simpleSubCategoryWithParent.name$"/> </actionGroup> <!--Open category one by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage1"> - <argument name="category" value="$$simpleSubCategoryOne$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryOne$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs1"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryTwo.name$$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryOne"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne1"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne1"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryTwo.name$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryOne"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne1"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne1"/> <!--Open category two by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryWithParentCategoryPage"> - <argument name="category" value="$$simpleSubCategoryWithParent$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryWithParent$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryTwo.name$$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryTwo.name$" stepKey="seeSubCategoryTwoInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryWithParent"/> <!--Move category one to the same level as category two--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToAdminCategoryPage2"/> <waitForPageLoad stepKey="waitForAdminCategoryPageLoad2"/> <actionGroup ref="MoveCategoryActionGroup" stepKey="moveSimpleSubCategoryOneToDefaultCategory"> - <argument name="childCategory" value="$$simpleSubCategoryOne.name$$"/> + <argument name="childCategory" value="$simpleSubCategoryOne.name$"/> <argument name="parentCategory" value="Default Category"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="/" stepKey="amOnStorefrontPage2"/> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage2"/> <waitForPageLoad stepKey="waitForPageToLoadAfterHomePageOpened2"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="verifyThatSubCategoryOneIsTopCategory"/> - <seeElement selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryTwo.name$$)}}" stepKey="verifyThatSubCategoryTwoIsTopCategory"/> - <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="mouseOverTopSubCategoryOne"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="verifyThatSubCategoryOneIsTopCategory"/> + <seeElement selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryTwo.name$)}}" stepKey="verifyThatSubCategoryTwoIsTopCategory"/> + <moveMouseOver selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="mouseOverTopSubCategoryOne"/> <waitForAjaxLoad stepKey="waitForAjaxOnMouseOverTopSubCategoryOne"/> - <seeElement selector="{{StorefrontNavigationSection.subCategory($$simpleSubCategoryWithParent.name$$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent2"/> + <seeElement selector="{{StorefrontNavigationSection.subCategory($simpleSubCategoryWithParent.name$)}}" stepKey="verifyThatSecondLevelIsSubCategoryWithParent2"/> <!--Open category one via navigation menu. Verify that subcategory is shown in layered navigation--> - <click selector="{{StorefrontNavigationSection.topCategory($$simpleSubCategoryOne.name$$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu2"/> + <click selector="{{StorefrontNavigationSection.topCategory($simpleSubCategoryOne.name$)}}" stepKey="openSimpleSubCategoryOneByNavigationMenu2"/> <actionGroup ref="CheckItemInLayeredNavigationActionGroup" stepKey="verifySimpleSubCategoryWithParentInLayeredNavigation2"> <argument name="itemType" value="Category"/> - <argument name="itemName" value="$$simpleSubCategoryWithParent.name$$"/> + <argument name="itemName" value="$simpleSubCategoryWithParent.name$"/> </actionGroup> <!--Open category one by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage2"> - <argument name="category" value="$$simpleSubCategoryOne$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryOne$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs2"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne2"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne2"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne2"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne2"/> <!--Open category subcategory by direct URL. Verify simple product is visible on it. Open this product and perform assertions--> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openFirstProductFromSubCategoryOneCategoryPage3"> - <argument name="category" value="$$simpleSubCategoryWithParent$$"/> - <argument name="product" value="$$productOne$$"/> + <argument name="category" value="$simpleSubCategoryWithParent$"/> + <argument name="product" value="$productOne$"/> </actionGroup> <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="Home" stepKey="seeHomePageInBreadcrumbs3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$simpleSubCategoryOne.name$$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent3"/> - <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$$productOne.name$$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryOneInBreadcrumbsOnSubCategoryOne3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$simpleSubCategoryOne.name$" stepKey="seeSubCategoryWithParentInBreadcrumbsOnSubCategoryWithParent3"/> + <see selector="{{StorefrontNavigationSection.breadcrumbs}}" userInput="$productOne.name$" stepKey="seeProductInBreadcrumbsOnSubCategoryOne3"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryToDefaultCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryToDefaultCategoryTest.xml index a8a8ede297b44..2122d73ca7e62 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryToDefaultCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryToDefaultCategoryTest.xml @@ -25,7 +25,7 @@ <after> <deleteData createDataKey="createDefaultCategory" stepKey="deleteDefaultCategory"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryAndCheckUrlRewritesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryAndCheckUrlRewritesTest.xml index ba6e6a43674c3..061bc795b2bff 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryAndCheckUrlRewritesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryAndCheckUrlRewritesTest.xml @@ -19,11 +19,13 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> - <createData entity="_defaultCategory" stepKey="createDefaultCategory"/> + <createData entity="FirstLevelSubCat" stepKey="createDefaultCategory"> + <field key="is_active">true</field> + </createData> </before> <after> <deleteData createDataKey="createDefaultCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open category page--> @@ -31,7 +33,7 @@ <waitForPageLoad stepKey="waitForPageToLoaded"/> <click selector="{{AdminCategorySidebarTreeSection.expandAll}}" stepKey="clickOnExpandTree"/> <waitForPageLoad stepKey="waitForCategoryToLoad"/> - <click selector="{{AdminCategorySidebarTreeSection.categoryInTree(_defaultCategory.name)}}" stepKey="selectCategory"/> + <click selector="{{AdminCategorySidebarTreeSection.categoryInTree(FirstLevelSubCat.name)}}" stepKey="selectCategory"/> <waitForPageLoad stepKey="waitForPageToLoad"/> <!--Create second level category--> @@ -54,18 +56,19 @@ <waitForPageLoad stepKey="waitForUrlRewritePage"/> <!--Search third level category Redirect Path, Target Path and Redirect Type--> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SimpleSubCategory.name_lwr}}" stepKey="fillRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SimpleSubCategory.name_lwr}}" stepKey="fillRequestPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad0"/> <!--Verify Category RedirectType--> - <see stepKey="verifyTheRedirectType" selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="No" /> + <see stepKey="verifyTheRedirectType" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="No" /> <!--Verify Redirect Path --> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{_defaultCategory.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" stepKey="verifyTheRedirectPath"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{FirstLevelSubCat.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" stepKey="verifyTheRedirectPath"/> <!--Verify Category Target Path--> - <see stepKey="verifyTheTargetPath" selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="catalog/category/view/id/{$categoryId}"/> + <see stepKey="verifyTheTargetPath" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="catalog/category/view/id/{$categoryId}"/> <!--Open Category Page --> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage1"/> @@ -74,7 +77,7 @@ <waitForPageLoad stepKey="waitForPageToLoad2"/> <!--Move the third level category under first level category --> - <dragAndDrop selector1="{{AdminCategorySidebarTreeSection.categoryInTree(SimpleSubCategory.name)}}" selector2="{{AdminCategorySidebarTreeSection.categoryInTree(_defaultCategory.name)}}" stepKey="moveCategory"/> + <dragAndDrop selector1="{{AdminCategorySidebarTreeSection.categoryInTree(SimpleSubCategory.name)}}" selector2="{{AdminCategorySidebarTreeSection.categoryInTree($$createDefaultCategory.name$$)}}" stepKey="m0oveCategory"/> <see selector="{{AdminCategoryModalSection.message}}" userInput="This operation can take a long time" stepKey="seeWarningMessage"/> <click selector="{{AdminCategoryModalSection.ok}}" stepKey="clickOkButtonOnWarningPopup"/> <waitForPageLoad stepKey="waitForPageToLoad3"/> @@ -83,31 +86,35 @@ <!--Open Url Rewrite page --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteIndexPage1"/> <waitForPageLoad stepKey="waitForUrlRewritePage1"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{_defaultCategory.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" stepKey="fillCategoryUrlKey1"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton1"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{FirstLevelSubCat.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" stepKey="fillCategoryUrlKey1"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> <waitForPageLoad stepKey="waitForPageToLoad4"/> <!--Verify new Redirect Path after move --> - <see stepKey="verifyTheRequestPathAfterMove" selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{_defaultCategory.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" /> + <see stepKey="verifyTheRequestPathAfterMove" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{FirstLevelSubCat.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" /> <!--Verify new Target Path after move --> - <see stepKey="verifyTheTargetPathAfterMove" selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="catalog/category/view/id/{$categoryId}" /> + <see stepKey="verifyTheTargetPathAfterMove" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="catalog/category/view/id/{$categoryId}" /> <!--Verify new RedirectType after move --> - <see stepKey="verifyTheRedirectTypeAfterMove" selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="No" /> + <see stepKey="verifyTheRedirectTypeAfterMove" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="No" /> <!--Verify before move Redirect Path displayed with associated Target Path and Redirect Type--> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SimpleSubCategory.name_lwr}}" stepKey="fillCategoryUrlKey2"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton2"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters2"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SimpleSubCategory.name_lwr}}" stepKey="fillCategoryUrlKey2"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters2"/> <waitForPageLoad stepKey="waitForPageToLoad5"/> - <see stepKey="verifyTheRedirectTypeAfterMove1" selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="Permanent (301)" /> - <see stepKey="verifyTheRequestPathAfterMove1" selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{_defaultCategory.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" /> - <see stepKey="verifyTheTargetPathAfterMove1" selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="{{_defaultCategory.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" /> + + + <see stepKey="verifyTheRedirectTypeAfterMove1" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="Permanent (301)" /> + <see stepKey="verifyTheRequestPathAfterMove1" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{FirstLevelSubCat.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" /> + <see stepKey="verifyTheTargetPathAfterMove1" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="{{FirstLevelSubCat.name_lwr}}2/{{SimpleSubCategory.name_lwr}}.html" /> <!--Verify before move Redirect Path directs to the category page--> - <amOnPage url="{{_defaultCategory.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" stepKey="openCategoryStoreFrontPage"/> + <amOnPage url="{{FirstLevelSubCat.name_lwr}}2/{{SubCategory.name_lwr}}/{{SimpleSubCategory.name_lwr}}.html" stepKey="openCategoryStoreFrontPage"/> <waitForPageLoad stepKey="waitForCategoryPageToLoad"/> - <seeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName(_defaultCategory.name)}}" stepKey="seeCategoryOnStoreNavigationBar"/> + <seeElement selector="{{StorefrontHeaderSection.NavigationCategoryByName(FirstLevelSubCat.name)}}" stepKey="seeCategoryOnStoreNavigationBar"/> <seeElement selector="{{StorefrontCategoryMainSection.CategoryTitle(SimpleSubCategory.name)}}" stepKey="seeCategoryInTitle"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryFromParentAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryFromParentAnchoredCategoryTest.xml index 271d78ab9cdb0..393d0c49c2e93 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryFromParentAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryFromParentAnchoredCategoryTest.xml @@ -28,7 +28,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryToAnotherPositionInCategoryTreeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryToAnotherPositionInCategoryTreeTest.xml index 6c403fc7714eb..801d925c0fd84 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryToAnotherPositionInCategoryTreeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveCategoryToAnotherPositionInCategoryTreeTest.xml @@ -28,7 +28,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="SecondLevelSubCat"> <argument name="categoryEntity" value="SecondLevelSubCat"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Category Page --> @@ -96,21 +96,23 @@ <!-- Open Url Rewrite page and see the url rewrite for the moved category --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteIndexPage"/> <waitForPageLoad stepKey="waitForUrlRewritePageLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="fillCategoryUrlKey"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> - <waitForPageLoad stepKey="waitForUrlPageToLoad"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="fillCategoryUrlKey"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForSearch"/> <!-- Verify new Redirect Path after move --> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('2')}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheRequestPathAfterMove"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('2', 'Request Path')}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheRequestPathAfterMove"/> <!-- Verify new Target Path after move --> - <see selector="{{AdminUrlRewriteIndexSection.targetPathColumn('2')}}" userInput="catalog/category/view/id/{$categoryId}" stepKey="verifyTheTargetPathAfterMove"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('2', 'Target Path')}}" userInput="catalog/category/view/id/{$categoryId}" stepKey="verifyTheTargetPathAfterMove"/> <!-- Verify new RedirectType after move --> - <see selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('2')}}" userInput="No" stepKey="verifyTheRedirectTypeAfterMove"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('2', 'Redirect Type')}}" userInput="No" stepKey="verifyTheRedirectTypeAfterMove"/> <!-- Verify before move Redirect Path displayed with associated Target Path and Redirect Type--> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SecondLevelSubCat.name_lwr}}" stepKey="fillTheCategoryUrlKey"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton2"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="Permanent (301)" stepKey="verifyTheRedirectTypeBeforeMove"/> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{_defaultCategory.name_lwr}}2/{{FirstLevelSubCat.name_lwr}}/{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheRequestPathBeforeMove"/> - <see selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheTargetPathBeforeMove"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SecondLevelSubCat.name_lwr}}" stepKey="fillTheCategoryUrlKey"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForSearch1"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="Permanent (301)" stepKey="verifyTheRedirectTypeBeforeMove"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{_defaultCategory.name_lwr}}2/{{FirstLevelSubCat.name_lwr}}/{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheRequestPathBeforeMove"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="{{SecondLevelSubCat.name_lwr}}.html" stepKey="verifyTheTargetPathBeforeMove"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveProductBetweenCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveProductBetweenCategoriesTest.xml index 7e6e79cd08c26..3f7d612a1fdbc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveProductBetweenCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveProductBetweenCategoriesTest.xml @@ -53,7 +53,7 @@ <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createSecondCategory" stepKey="deleteSecondCategory"/> <deleteData createDataKey="createAnchoredCategory1" stepKey="deleteAnchoredCategory1"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create the anchored category <Cat1_anchored> --> <actionGroup ref="AdminAnchorCategoryActionGroup" stepKey="anchorCategory"> @@ -129,7 +129,7 @@ <waitForPageLoad stepKey="waitForRefresh"/> <see userInput="2 cache type(s) refreshed." stepKey="seeCacheRefreshedMessage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Open frontend --> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="onFrontend"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml index f7fd81f28199f..d56f64d72a1c1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMultipleWebsitesUseDefaultValuesTest.xml @@ -22,9 +22,9 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteSecondWebsite"> <argument name="websiteName" value="Second Website"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createAdditionalWebsite"> <argument name="newWebsiteName" value="Second Website"/> <argument name="websiteCode" value="second_website"/> @@ -81,4 +81,4 @@ <seeCheckboxIsChecked selector="{{AdminProductFormSection.productTaxClassUseDefault}}" stepKey="seeTaxClassCheckboxChecked"/> <seeCheckboxIsChecked selector="{{AdminProductFormSection.visibilityUseDefault}}" stepKey="seeVisibilityCheckboxChecked"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml index 5dd8b2e430941..ab1ced89175bc 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml @@ -78,7 +78,7 @@ </before> <after> <!--Logout as admin--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!--Delete created data--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> @@ -90,6 +90,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deletecreateConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deletecreateConfigChildProduct1"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product Index Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCategoryIndexerInUpdateOnScheduleModeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCategoryIndexerInUpdateOnScheduleModeTest.xml index 2283a0e4d6158..b547fbe69fbf7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCategoryIndexerInUpdateOnScheduleModeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCategoryIndexerInUpdateOnScheduleModeTest.xml @@ -69,7 +69,7 @@ <deleteData createDataKey="createCategoryA" stepKey="deleteCategoryA"/> <deleteData createDataKey="createCategoryC" stepKey="deleteCategoryC"/> <deleteData createDataKey="createCategoryB" stepKey="deleteCategoryB"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Case: change product category from product page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCustomURLKeyPreservedWhenAssignedToCategoryWithoutCustomURLKey.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCustomURLKeyPreservedWhenAssignedToCategoryWithoutCustomURLKey.xml index df09768139533..400cc891b3c91 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCustomURLKeyPreservedWhenAssignedToCategoryWithoutCustomURLKey.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductCustomURLKeyPreservedWhenAssignedToCategoryWithoutCustomURLKey.xml @@ -47,7 +47,7 @@ <argument name="customStore" value="storeViewData"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml index 6f65865924bad..1f7b88e8bb27f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml @@ -89,7 +89,10 @@ <!--Delete category--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="NavigateToAndResetProductGridToDefaultViewAfterTest"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <waitForPageLoad stepKey="waitForProductGridPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByDateAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByDateAttributeTest.xml index d9f894fa5736b..8c334cb84be01 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByDateAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByDateAttributeTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createSimpleProductWithDate" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttribute"/> <waitForPageLoad stepKey="wait1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml index 59be8157d2f87..f32845072ec02 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductImageAssignmentForMultipleStoresTest.xml @@ -54,7 +54,7 @@ <!-- Clear Filter Product --> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <!-- Logout Admin --> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!-- Search Product and Open Edit --> <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchProduct"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml index a882c6e7817ce..5f089aad256b7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductStatusAttributeDisabledByDefaultTest.xml @@ -35,7 +35,7 @@ <waitForPageLoad stepKey="waitForSaveAttribute1"/> <actionGroup ref="ClearCacheActionGroup" stepKey="clearCache1"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttribute"/> <waitForPageLoad stepKey="wait1"/> @@ -56,4 +56,4 @@ <dontSeeCheckboxIsChecked selector="{{AdminProductFormSection.productStatus}}" stepKey="dontSeeCheckboxEnableProductIsChecked"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml index 0b7e2a70735c3..8e8f3ebccafb1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml @@ -34,7 +34,7 @@ <comment userInput="Delete product" stepKey="commentDeleteProduct"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Change product type to Downloadable--> <comment userInput="Change product type to Downloadable" stepKey="commentCreateDownloadable"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveCustomOptionsFromProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveCustomOptionsFromProductTest.xml index fb54b0b601d85..90fd42f8b4c95 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveCustomOptionsFromProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveCustomOptionsFromProductTest.xml @@ -28,7 +28,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProductWithOptions"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- Edit Simple Product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml index 47f497b381553..5e29bf30b4bf2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageAffectsAllScopesTest.xml @@ -67,7 +67,7 @@ <deleteData createDataKey="product" stepKey="deleteFirstProduct"/> <magentoCLI stepKey="reindex" command="indexer:reindex"/> <magentoCLI stepKey="flushCache" command="cache:flush"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create product--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageFromCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageFromCategoryTest.xml index ef276114b4de5..b3e5900c9bb76 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageFromCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRemoveImageFromCategoryTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="DeleteCategory"> <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to create a new category with image --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml index ebae27a1f7182..45c2c9d379033 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml @@ -18,7 +18,7 @@ <group value="Catalog"/> </annotations> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml index 05008b32ed4fb..5f489e337b01a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRestrictedUserAddCategoryFromProductPageTest.xml @@ -32,7 +32,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetFiltersIfExist"/> - <actionGroup ref="logout" stepKey="logoutOfUser"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfUser"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!--Delete created data--> <comment userInput="Delete created data" stepKey="commentDeleteCreatedData"/> @@ -47,7 +47,7 @@ <argument name="userName" value="{{admin2.username}}"/> </actionGroup> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Create user role--> <comment userInput="Create user role" stepKey="commentCreateUserRole"/> @@ -74,7 +74,7 @@ </actionGroup> <!--Log out of admin and login with newly created user--> <comment userInput="Log out of admin and login with newly created user" stepKey="commentLoginWithNewUser"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsNewUser"> <argument name="adminUser" value="admin2"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml index 9d19a1dedf7ef..190a051c16d44 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminShouldBeAbleToAssociateSimpleProductToWebsitesTest.xml @@ -44,7 +44,7 @@ <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="resetFiltersOnStoresIndexPage"/> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPageToResetFilters"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnProductIndexPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Go to product page in admin panel to edit --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml index ff8240655ca03..3d505b9f893eb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest.xml @@ -34,7 +34,7 @@ <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="firstProduct" stepKey="deleteFirstProduct"/> <deleteData createDataKey="secondProduct" stepKey="deleteSecondProduct"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Go to the first product edit page --> @@ -188,7 +188,7 @@ <after> <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Go to the product edit page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductSetEditContentTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductSetEditContentTest.xml index 1e1fe4572b28d..80e245818e216 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductSetEditContentTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductSetEditContentTest.xml @@ -30,7 +30,7 @@ <argument name="product" value="SimpleProduct"/> </actionGroup> <!--Admin Logout--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml index 0c0b8751a732e..84eb3a843aa1f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml @@ -27,6 +27,8 @@ <createData entity="SimpleProduct2" stepKey="simpleProduct4"/> <createData entity="SimpleProduct2" stepKey="simpleProduct5"/> <createData entity="SimpleProduct2" stepKey="simpleProduct6"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Delete simple product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml index b20a024a7c586..16bc76cb6446a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="ResetWebUrlOptionsActionGroup" stepKey="resetUrlOption"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Assign Custom Website to Simple Product --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresAttributeSetNavigateMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresAttributeSetNavigateMenuTest.xml index ed29c281b804c..544ab05d8783b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresAttributeSetNavigateMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresAttributeSetNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToAttributeSetPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresProductNavigateMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresProductNavigateMenuTest.xml index 28a33c4f20c01..37571d7b44635 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresProductNavigateMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminStoresProductNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToProductAttributePage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml index 4bcb82372e801..ee8dab9c0ee37 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml @@ -82,7 +82,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Go to storefront product page an check price box css--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml index 44b4e60973907..c651d2db6a7ce 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml @@ -36,7 +36,10 @@ <deleteData createDataKey="product" stepKey="deleteProduct"/> <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Assert attribute presence in storefront product additional information --> <amOnPage url="/$$product.custom_attributes[url_key]$$.html" stepKey="onProductPage1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndCheckDefaultUrlKeyOnStoreViewTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndCheckDefaultUrlKeyOnStoreViewTest.xml index d8d462f850f8f..0f4e6e2854948 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndCheckDefaultUrlKeyOnStoreViewTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndCheckDefaultUrlKeyOnStoreViewTest.xml @@ -29,7 +29,7 @@ <argument name="storeGroupName" value="customStore.name"/> </actionGroup> <deleteData createDataKey="rootCategory" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Store Page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndMakeInactiveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndMakeInactiveTest.xml index 479249ca678dd..b121ba46410e4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndMakeInactiveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryAndMakeInactiveTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createDefaultCategory" stepKey="deleteCreatedCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open category page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryNameWithStoreViewTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryNameWithStoreViewTest.xml index 2cb4a6b6dd436..51d8b9e1eaf37 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryNameWithStoreViewTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryNameWithStoreViewTest.xml @@ -29,7 +29,7 @@ <argument name="storeGroupName" value="customStore.name"/> </actionGroup> <deleteData createDataKey="rootCategory" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open store page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml index 01eba2976c3d6..299298266d061 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryStoreUrlKeyTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> <argument name="categoryEntity" value="_defaultCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create category, change store view to default --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryUrlKeyWithStoreViewTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryUrlKeyWithStoreViewTest.xml index e7c4a8a093e19..c0c8f53307b20 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryUrlKeyWithStoreViewTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryUrlKeyWithStoreViewTest.xml @@ -29,7 +29,7 @@ <argument name="storeGroupName" value="customStore.name"/> </actionGroup> <deleteData createDataKey="rootCategory" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Store Page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithInactiveIncludeInMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithInactiveIncludeInMenuTest.xml index 0c705c180d073..d6c581b18beff 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithInactiveIncludeInMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithInactiveIncludeInMenuTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createDefaultCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> @@ -54,10 +54,11 @@ <waitForPageLoad stepKey="waitForUrlRewritePage"/> <!--Verify Updated Category UrlKey--> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{SimpleRootSubCategory.url_key}}" stepKey="fillUpdatedCategoryUrlKey"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{SimpleRootSubCategory.url_key}}" stepKey="fillUpdatedCategoryUrlKey"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <see stepKey="seeCategoryUrlKey" selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{SimpleRootSubCategory.url_key}}.html" /> + <see stepKey="seeCategoryUrlKey" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{SimpleRootSubCategory.url_key}}.html" /> <!--Verify Updated Category UrlKey directs to category Store Front--> <amOnPage url="{{SimpleRootSubCategory.url_key}}.html" stepKey="seeTheCategoryInStoreFrontPage"/> <waitForPageLoad time="60" stepKey="waitForStoreFrontPageLoad"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithProductsTest.xml index ad110ceee32d2..065ebb74785d4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateCategoryWithProductsTest.xml @@ -25,7 +25,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Category Page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryAndAddProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryAndAddProductsTest.xml index cebf67ae2ebcf..8a31145f7349d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryAndAddProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryAndAddProductsTest.xml @@ -54,7 +54,7 @@ </actionGroup> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Select Created Category--> <magentoCLI command="indexer:reindex" stepKey="reindexBeforeFlow"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryIncludeInNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryIncludeInNavigationTest.xml index d7ce22bdc0097..6575fd1f1c977 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryIncludeInNavigationTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryIncludeInNavigationTest.xml @@ -51,7 +51,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewFr"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Verify Category is not listed in navigation menu--> <amOnPage url="/{{CatNotIncludeInMenu.name_lwr}}.html" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml index 2b14973d6ce32..2ae3c67cb222d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml @@ -52,7 +52,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewFr"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Select Created Category--> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml index 60e7f03824ab7..2c45e957d801c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml @@ -38,7 +38,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml index 7624ad0557b47..4e80f95bbf390 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml @@ -38,7 +38,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="customStoreFR"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index a848eb3d11e61..7096e547c5aa7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -36,7 +36,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductTierPrice300InStock.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml index ff3f56b566b38..270b95b7e52c5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductDisabled.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml index 09ddc18aff4bd..e9c2ed1511ce3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml @@ -33,7 +33,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductEnabledFlat.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI stepKey="unsetFlatCatalogProduct" command="config:set catalog/frontend/flat_catalog_product 0"/> </after> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index 94aec4cc95d1d..17a91ed2cf4f4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductNotVisibleIndividually.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockUnassignFromCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockUnassignFromCategoryTest.xml index fa3317aa815d9..84f2c4552ae6c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockUnassignFromCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockUnassignFromCategoryTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="$$initialSimpleProduct.sku$$"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Search default simple product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 95b74f4d38b3f..2490782d86b8b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductRegularPrice245InStock.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index af190890ac351..2f0ef84d4be0d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductRegularPrice32501InStock.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index 626c3d00a5caf..5c196744f0181 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductRegularPrice325InStock.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml index 13782da076f69..4b13323afdc44 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductRegularPriceCustomOptions.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 285ceb3c4d722..ec19a2a496f9f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteCreatedProduct"> <argument name="sku" value="{{simpleProductRegularPrice32503OutOfStock.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default simple product in the grid --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml index 4dea6663e61bf..df3f0529b1bd4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createThreeLevelNestedCategories" stepKey="deleteThreeNestedCategories"/> <deleteData createDataKey="createTwoLevelNestedCategories" stepKey="deleteTwoLevelNestedCategory"/> @@ -68,21 +68,27 @@ <waitForPageLoad stepKey="waitForUrlRewritePage"/> <!-- Verify third level category's Redirect Path, Target Path and Redirect Type after the URL Update --> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" + dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" + visible="true" + stepKey="clickOnResetButton"/> <waitForPageLoad stepKey="waitForPageToLoad0"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="updatedurl" stepKey="fillUpdatedUrlInRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="updatedurl" stepKey="fillUpdatedUrlInRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad2"/> - <see stepKey="seeTheRedirectType" selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="No" /> - <see stepKey="seeTheTargetPath" selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="catalog/category/view/id/{$categoryId}"/> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updatedurl.html" stepKey="seeTheRedirectPath"/> + <see stepKey="seeTheRedirectType" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="No" /> + <see stepKey="seeTheTargetPath" selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="catalog/category/view/id/{$categoryId}"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updatedurl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's old URL path doesn't show redirect path--> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton1"/> + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickOnResetButton1"/> <waitForPageLoad stepKey="waitForPageToLoad3"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{Three_nested_categories.name_lwr}}" stepKey="fillOldUrlInRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton1"/> + + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{Three_nested_categories.name_lwr}}" stepKey="fillOldUrlInRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> <waitForPageLoad stepKey="waitForPageToLoad4"/> - <see stepKey="seeEmptyRecodsMessage" selector="{{AdminUrlRewriteIndexSection.emptyRecords}}" userInput="We couldn't find any records."/> + <see stepKey="seeEmptyRecodsMessage" selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records."/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml index ee1ed5f97edfa..fddaced13fa4d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml @@ -34,7 +34,7 @@ <deleteData createDataKey="createThreeLevelNestedCategories" stepKey="deleteThreeNestedCategories"/> <deleteData createDataKey="createTwoLevelNestedCategories" stepKey="deleteTwoLevelNestedCategory"/> <deleteData createDataKey="createDefaultCategory" stepKey="deleteDefaultCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Category page --> @@ -66,23 +66,28 @@ <waitForPageLoad stepKey="waitForUrlRewritePage"/> <!-- Verify third level category's Redirect Path, Target Path and Redirect Type after the URL update --> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" + dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" + visible="true" + stepKey="clickOnResetButton"/> <waitForPageLoad stepKey="waitForPageToLoad2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="updateredirecturl" stepKey="fillUpdatedURLInRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="updateredirecturl" stepKey="fillUpdatedURLInRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad3"/> - <see selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="No" stepKey="seeTheRedirectType"/> - <see selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="catalog/category/view/id/{$categoryId}" stepKey="seeTheTargetPath"/> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheRedirectPath"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="No" stepKey="seeTheRedirectType"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="catalog/category/view/id/{$categoryId}" stepKey="seeTheTargetPath"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's Redirect path, Target Path and Redirect type for old URL --> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton1"/> + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickOnResetButton1"/> <waitForPageLoad stepKey="waitForPageToLoad4"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$$createThreeLevelNestedCategories.name$$" stepKey="fillOldUrlInRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton1"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$$createThreeLevelNestedCategories.name$$" stepKey="fillOldUrlInRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> <waitForPageLoad stepKey="waitForPageToLoad5"/> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/$$createThreeLevelNestedCategories.name$$.html" stepKey="seeTheRedirectPathForOldUrl"/> - <see selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheTargetPathForOldUrl"/> - <see selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="Permanent (301)" stepKey="seeTheRedirectTypeForOldUrl"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/$$createThreeLevelNestedCategories.name$$.html" stepKey="seeTheRedirectPathForOldUrl"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheTargetPathForOldUrl"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="Permanent (301)" stepKey="seeTheRedirectTypeForOldUrl"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml index 0e9b9431dcfa6..cea09b0cdb4bd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml index f621813f4f8c0..77de42bdbac21 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml @@ -30,7 +30,7 @@ <after> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryAndSearchTest.xml index 021ed5593c738..918cda5274216 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml index d74a6ce508b88..5f6f44110bfb4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml index aa90d018f7710..393c280eedf1b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml @@ -31,7 +31,7 @@ <argument name="sku" value="{{updateVirtualProductRegularPrice99OutOfStock.sku}}"/> </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml index 94ddb3dc5e5da..9658597a04717 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml index a6a629b35091e..9d3d315487d65 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml index 04110dbd73a4c..f5571633c2da4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml @@ -8,7 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="UpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest"> + <test name="AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest"> <annotations> <stories value="Update Virtual Product"/> <title value="Update Virtual Product with Tier Price (In Stock) Visible in Category and Search"/> @@ -17,147 +17,117 @@ <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30166"/> - </skip> </annotations> <before> - <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> <createData entity="SimpleSubCategory" stepKey="initialCategoryEntity"/> <createData entity="defaultVirtualProduct" stepKey="initialVirtualProduct"> <requiredEntity createDataKey="initialCategoryEntity"/> </createData> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> + <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </before> + <after> + <deleteData createDataKey="initialCategoryEntity" stepKey="deleteInitialCategory"/> + <deleteData createDataKey="categoryEntity" stepKey="deleteCategory" /> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="updateVirtualProductTierPriceInStock"/> </actionGroup> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> - <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> - <!-- Search default virtual product in the grid --> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPage1"/> - <waitForPageLoad stepKey="waitForProductCatalogPage1"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="clickClearAllFilter" /> - <fillField selector="{{AdminProductGridFilterSection.keywordSearch}}" userInput="$$initialVirtualProduct.name$$" stepKey="fillVirtualProductNameInKeywordSearch"/> - <click selector="{{AdminProductGridFilterSection.keywordSearchButton}}" stepKey="clickKeywordSearchButton"/> - <waitForPageLoad stepKey="waitForProductSearch"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyCreatedVirtualProduct"/> - <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <actionGroup ref="FilterAndSelectProductActionGroup" stepKey="openProductEditPageBySKU"> + <argument name="productSku" value="$initialVirtualProduct.sku$"/> + </actionGroup> <!-- Update virtual product with tier price --> - <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="fillProductName"/> - <fillField selector="{{AdminProductFormSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillProductSku"/> - <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="fillProductPrice"/> + <actionGroup ref="FillMainProductFormNoWeightActionGroup" stepKey="fillNewProductData"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!-- Press enter to validate advanced pricing link --> <pressKey selector="{{AdminProductFormSection.productPrice}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::ENTER]" stepKey="pressEnterKey"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/> - <click selector="{{AdminProductFormAdvancedPricingSection.customerGroupPriceAddButton}}" stepKey="clickCustomerGroupPriceAddButton"/> - <scrollTo selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" x="50" y="0" stepKey="scrollToProductTierPriceQuantityInputTextBox"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.website}}" stepKey="selectProductTierPriceWebsiteInput"/> - <selectOption selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.customer_group}}" stepKey="selectProductTierPriceCustomerGroupInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnVirtualProduct.qty}}" stepKey="fillProductTierPriceQuantityInput"/> - <fillField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnVirtualProduct.price}}" stepKey="selectProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDoneButton"/> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialog"/> + <actionGroup ref="AdminProductFormAdvancedPricingAddTierPriceActionGroup" stepKey="addTierPrice"> + <argument name="website" value="{{tierPriceOnVirtualProduct.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnVirtualProduct.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnVirtualProduct.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnVirtualProduct.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{updateVirtualProductTierPriceInStock.productTaxClass}}" stepKey="selectProductStockClass"/> - <fillField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{updateVirtualProductTierPriceInStock.quantity}}" stepKey="fillProductQuantity"/> - <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.status}}" stepKey="selectStockStatusInStock"/> - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> - <waitForPageLoad stepKey="waitForCategory1"/> - <click selector="{{AdminProductFormSection.selectCategory($$initialCategoryEntity.name$$)}}" stepKey="unselectInitialCategory"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory" /> - <waitForPageLoad stepKey="waitForCategory2"/> - <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneAdvancedCategorySelect"/> + <actionGroup ref="RemoveCategoryFromProductActionGroup" stepKey="unselectInitialCategory"> + <argument name="categoryName" value="$initialCategoryEntity.name$"/> + </actionGroup> + <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> + <argument name="categoryName" value="$categoryEntity.name$"/> + </actionGroup> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductTierPriceInStock.visibility}}" stepKey="selectVisibility"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> - <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{updateVirtualProductTierPriceInStock.urlKey}}" stepKey="fillUrlKey"/> - <scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/> - <click selector="{{AdminProductFormSection.save}}" stepKey="clickSaveButton"/> - <waitForPageLoad stepKey="waitForVirtualProductSaved"/> - <!-- Verify we see success message --> - <see selector="{{AdminProductFormSection.successMessage}}" userInput="You saved the product." stepKey="seeAssertVirtualProductSaveSuccessMessage"/> + <actionGroup ref="SetProductUrlKeyByStringActionGroup" stepKey="updateUrlKey"> + <argument name="urlKey" value="{{updateVirtualProductTierPriceInStock.urlKey}}"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> <!-- Search updated virtual product(from above step) in the grid --> - <amOnPage url="{{ProductCatalogPage.url}}" stepKey="OpenProductCatalogPageToSearchUpdatedVirtualProduct"/> - <waitForPageLoad stepKey="waitForProductCatalogPageToLoad"/> - <conditionalClick selector="{{AdminProductGridFilterSection.clearAll}}" dependentSelector="{{AdminProductGridFilterSection.clearAll}}" visible="true" stepKey="clickClearAll"/> - <click selector="{{AdminProductGridFilterSection.filters}}" stepKey="clickFiltersButton"/> - <fillField selector="{{AdminProductGridFilterSection.nameFilter}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="fillVirtualProductNameInNameFilter"/> - <fillField selector="{{AdminProductGridFilterSection.skuFilter}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillVirtualProductSku"/> - <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyUpdatedVirtualProductVisibleInGrid"/> - <waitForPageLoad stepKey="waitUntilVirtualProductPageIsOpened"/> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!-- Verify customer see updated virtual product with tier price(from the above step) in the product form page --> - <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeProductName"/> - <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="seeProductSku"/> - <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="seeProductPrice"/> - <click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink1"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceWebsiteSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.website}}" stepKey="seeProductTierPriceWebsiteInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceCustGroupSelect('0')}}" userInput="{{tierPriceOnVirtualProduct.customer_group}}" stepKey="seeProductTierPriceCustomerGroupInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceQtyInput('0')}}" userInput="{{tierPriceOnVirtualProduct.qty}}" stepKey="seeProductTierPriceQuantityInput"/> - <seeInField selector="{{AdminProductFormAdvancedPricingSection.productTierPriceFixedPriceInput('0')}}" userInput="{{tierPriceOnVirtualProduct.price}}" stepKey="seeProductTierPriceFixedPrice"/> - <click selector="{{AdminProductFormAdvancedPricingSection.advancedPricingCloseButton}}" stepKey="clickAdvancedPricingCloseButton"/> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="verifyProductInAdminEditForm"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> + <actionGroup ref="AdminProductFormOpenAdvancedPricingDialogActionGroup" stepKey="openAdvancedPricingDialogAgain"/> + <actionGroup ref="AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup" stepKey="checkTierPrice"> + <argument name="rowNumber" value="0"/> + <argument name="website" value="{{tierPriceOnVirtualProduct.website}}"/> + <argument name="customerGroup" value="{{tierPriceOnVirtualProduct.customer_group}}"/> + <argument name="quantity" value="{{tierPriceOnVirtualProduct.qty}}"/> + <argument name="priceType" value="Fixed"/> + <argument name="amount" value="{{tierPriceOnVirtualProduct.price}}"/> + </actionGroup> + <actionGroup ref="AdminProductFormCloseAdvancedPricingDialogActionGroup" stepKey="closeAdvancedPricingModal"/> <seeInField selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{updateVirtualProductTierPriceInStock.productTaxClass}}" stepKey="seeProductTaxClass"/> - <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{updateVirtualProductTierPriceInStock.quantity}}" stepKey="seeProductQuantity"/> - <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.status}}" stepKey="seeProductStockStatus"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <grabMultiple selector="{{AdminProductFormSection.selectMultipleCategories}}" stepKey="selectedCategories" /> <assertEquals stepKey="assertSelectedCategories"> <actualResult type="variable">selectedCategories</actualResult> - <expectedResult type="array">[$$categoryEntity.name$$]</expectedResult> + <expectedResult type="array">[$categoryEntity.name$]</expectedResult> </assertEquals> <click selector="{{AdminProductFormSection.done}}" stepKey="clickOnDoneOnCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{updateVirtualProductTierPriceInStock.visibility}}" stepKey="seeVisibility"/> - <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> + + <conditionalClick selector="{{AdminProductSEOSection.sectionHeader}}" dependentSelector="{{AdminProductSEOSection.useDefaultUrl}}" visible="false" stepKey="openSearchEngineOptimizationSection"/> + <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="scrollToAdminProductSEOSection"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{updateVirtualProductTierPriceInStock.urlKey}}" stepKey="seeUrlKey"/> <!--Verify customer see updated virtual product link on category page --> - <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> - <waitForPageLoad stepKey="waitForCategoryPageLoad"/> - <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductLinkOnCategoryPage"/> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="openCategoryPageOnFrontend"> + <argument name="category" value="$categoryEntity$"/> + </actionGroup> + <actionGroup ref="AssertProductOnCategoryPageActionGroup" stepKey="checkProductOnCategoryPage"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> <!--Verify customer see updated virtual product with tier price on product storefront page --> - <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductTierPriceInStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{updateVirtualProductTierPriceInStock.price}}" stepKey="seeVirtualProductPriceOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="seeVirtualProductSku"/> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{updateVirtualProductTierPriceInStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{updateVirtualProductTierPriceInStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierPriceOnVirtualProduct.qty}} for ${{tierPriceOnVirtualProduct.price}} each and save 38%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertProductInStorefrontProductPageActionGroup" stepKey="verifyProductOnFrontend"> + <argument name="product" value="updateVirtualProductTierPriceInStock"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="{{updateVirtualProductTierPriceInStock.storefrontStatus}}" stepKey="assertStockAvailableOnProductPage"/> + <see selector="{{StorefrontProductInfoMainSection.tierPriceText}}" userInput="Buy {{tierPriceOnVirtualProduct.qty}} for ${{tierPriceOnVirtualProduct.price}} each and save 38%" stepKey="assertTierPriceTextOnProductPage"/> <!--Verify customer see updated virtual product link on magento storefront page and is searchable by sku --> - <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductTierPriceInStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> - <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductTierPriceInStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductTierPriceInStock.name}}" stepKey="seeVirtualProductName"/> - <grabTextFrom selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" stepKey="tierPriceTextOnStorefrontPage"/> - <assertEquals stepKey="assertTierPriceTextOnCategoryPage"> - <expectedResult type="string">As low as ${{tierPriceOnVirtualProduct.price}}</expectedResult> - <actualResult type="variable">tierPriceTextOnStorefrontPage</actualResult> - </assertEquals> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchProductBySku"> + <argument name="phrase" value="{{updateVirtualProductTierPriceInStock.sku}}"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchSeeProductByNameActionGroup" stepKey="checkProductInSearchResults"> + <argument name="productName" value="{{updateVirtualProductTierPriceInStock.name}}"/> + </actionGroup> + <see selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" userInput="As low as ${{tierPriceOnVirtualProduct.price}}" stepKey="assertTierPriceTextOnCategoryPage"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml index 0edc487e71edf..5c0b7c31756ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml index e513d007e6a09..eeb85e8d6fc2e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -33,7 +33,7 @@ </actionGroup> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search default virtual product in the grid page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminVerifyProductOrderTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminVerifyProductOrderTest.xml index b61be7fd95a58..09ddcd040bea4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminVerifyProductOrderTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminVerifyProductOrderTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="GoToProductCatalogPageActionGroup" stepKey="goToProductCatalogPage"/> <actionGroup ref="VerifyProductTypeOrder" stepKey="verifyProductTypeOrder"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdvanceCatalogSearchSimpleProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdvanceCatalogSearchSimpleProductTest.xml index 3125ba3decce6..14f4a6f6d1cfb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdvanceCatalogSearchSimpleProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdvanceCatalogSearchSimpleProductTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="product" stepKey="delete"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> </test> <test name="AdvanceCatalogSearchSimpleProductBySkuTest"> @@ -106,7 +106,7 @@ </before> <after> <deleteData createDataKey="product" stepKey="delete"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 4e0e8d03f59d5..1fe42a331c80c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -36,6 +36,7 @@ <createData entity="Simple_US_Customer" stepKey="customer"/> <!--Login as admin--> <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + <createData entity="CustomerAccountSharingGlobal" stepKey="setConfigCustomerAccountToGlobal"/> </before> <!--Create website, Sore adn Store View--> @@ -328,7 +329,8 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> <argument name="websiteName" value="secondWebsite"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!--Do reindex and flush cache--> <magentoCLI command="indexer:reindex" stepKey="reindex"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml index 1e297586ecb65..d5dee9e462560 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest.xml @@ -30,7 +30,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Navigate to Stores > Attributes > Product.--> @@ -89,7 +89,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Generate date for use as default value, needs to be MM/d/YYYY --> @@ -149,7 +149,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Navigate to Stores > Attributes > Product.--> @@ -203,7 +203,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Navigate to Stores > Attributes > Product.--> @@ -290,7 +290,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Navigate to Stores > Attributes > Product.--> @@ -358,7 +358,7 @@ <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> <waitForPageLoad stepKey="waitForDeletion"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Navigate to Stores > Attributes > Product.--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteCategoriesTest.xml index 8609d50fecaf2..604c01f05b838 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteCategoriesTest.xml @@ -36,7 +36,7 @@ <createData entity="NewRootCategory" stepKey="createNewRootCategoryA"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/> <deleteData createDataKey="createProduct3" stepKey="deleteProduct3"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml index 0daf8361ef9d1..eb6661e12116d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml @@ -72,7 +72,10 @@ <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> <!-- Logout --> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to Stores > Attributes > Products. Search and select the product attribute that was used to create the configurable product--> <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openProductAttributeFromSearchResultInGrid"> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/DisplayRefreshCacheAfterChangingCategoryPageLayoutTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/DisplayRefreshCacheAfterChangingCategoryPageLayoutTest.xml index 1f71ec1e6a850..5a57bd844aa8d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/DisplayRefreshCacheAfterChangingCategoryPageLayoutTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/DisplayRefreshCacheAfterChangingCategoryPageLayoutTest.xml @@ -30,7 +30,7 @@ <!-- Delete category and log out --> <comment userInput="Delete category and log out" stepKey="deleteCategoryAndLogOut"/> <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logOutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOutFromAdmin"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> <!-- Navigate to category details page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml index 232321610eadc..0400de5227cf3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CAdminTest.xml @@ -21,7 +21,7 @@ </skip> </annotations> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Login to Admin Area--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml index c75abdbe43e24..96907eb091b45 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml @@ -43,7 +43,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open product page--> <amOnPage url="{{StorefrontProductPage.url($$createProductDefault.name$$)}}" stepKey="goToProductDefaultPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index c8a7cdee66b53..9e0dea7e06ded 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -34,7 +34,7 @@ <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="$$createCategory.name$$.html" stepKey="goToCategoryStorefront2"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml index 89e784d67eaea..f2c5750a2b18e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/SaveProductWithCustomOptionsSecondWebsiteTest.xml @@ -53,7 +53,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteTestWebsite"> <argument name="websiteName" value="Second Website"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="EnableWebUrlOptionsActionGroup" stepKey="addStoreCodeToUrls"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml index 3c1bcb3b352cd..fe37f2110acc9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml @@ -171,7 +171,7 @@ <actionGroup ref="ResetSearchEngineConfigurationActionGroup" stepKey="resetCatalogSearchConfiguration"/> <magentoCLI command="indexer:reindex" stepKey="performReindexAfterElasticSearchDisable"/> <magentoCLI command="cache:flush" stepKey="cleanCacheAfterElasticSearchDisable"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Storefront on the myCategory page--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml new file mode 100644 index 0000000000000..6817969de65c3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml @@ -0,0 +1,65 @@ +<?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="StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest"> + <annotations> + <features value="Catalog"/> + <title value="Apply discount tier price and custom price values for simple product"/> + <description value="Apply discount tier price and custom price values for simple product"/> + <severity value="MAJOR"/> + <group value="Catalog"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <createData entity="ApiSimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">100.00</field> + </createData> + + <createData entity="tierProductPriceDiscount" stepKey="addTierPrice"> + <requiredEntity createDataKey="createProduct"/> + </createData> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openAdminProductEditPage"> + <argument name="productId" value="$createProduct.id$"/> + </actionGroup> + + <actionGroup ref="AddSpecialPriceToProductActionGroup" stepKey="addSpecialPriceToProduct"> + <argument name="price" value="65.00"/> + </actionGroup> + + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductForm"/> + + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontProductDetailPageNameActionGroup" stepKey="assertProductNameText"> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontProductDetailPageTierPriceActionGroup" stepKey="assertProductTierPriceText"> + <argument name="tierProductPriceDiscountQuantity" value="{{tierProductPriceDiscount.quantity}}"/> + <argument name="productPriceWithAppliedTierPriceDiscount" value="64.00"/> + <argument name="productSavedPricePercent" value="2"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontProductDetailPageFinalPriceActionGroup" stepKey="assertProductFinalPriceText"> + <argument name="finalProductPrice" value="65.00"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCatalogNavigationMenuUIDesktopTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCatalogNavigationMenuUIDesktopTest.xml index 22ec0048497fa..68ced18a0a7dd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCatalogNavigationMenuUIDesktopTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCatalogNavigationMenuUIDesktopTest.xml @@ -29,7 +29,7 @@ <argument name="theme" value="{{MagentoLumaTheme.name}}"/> </actionGroup> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Content > Themes. Change theme to Blank --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCategoryHighlightedAndProductDisplayedTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCategoryHighlightedAndProductDisplayedTest.xml index 3e72df9133898..b8a9a9cb3e0e6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCategoryHighlightedAndProductDisplayedTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCategoryHighlightedAndProductDisplayedTest.xml @@ -47,7 +47,7 @@ <deleteData createDataKey="category2" stepKey="deleteCategory2"/> <deleteData createDataKey="category3" stepKey="deleteCategory3"/> <deleteData createDataKey="category4" stepKey="deleteCategory4"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Storefront home page--> <comment userInput="Open Storefront home page" stepKey="openStorefrontHomePage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml index 4eef6a2c06800..dc053bb990685 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml @@ -176,7 +176,7 @@ <deleteData createDataKey="createSimpleProductThirtyFive" stepKey="deleteProductThirtyFive"/> <deleteData createDataKey="createSimpleProductThirtySix" stepKey="deleteProductThirtySix"/> <deleteData createDataKey="createSimpleProductThirtySeven" stepKey="deleteProductThirtySeven"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Verify configuration for default number of products displayed in the grid view--> <comment userInput="Verify configuration for default number of products displayed in the grid view" stepKey="commentVerifyDefaultValues"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml index 30461a30e53cb..2695c0f07f19e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontEnsureThatAccordionAnchorIsVisibleOnViewportOnceClickedTest.xml @@ -69,6 +69,9 @@ <deleteData createDataKey="createThirdAttribute" stepKey="deleteThirdAttribute"/> <deleteData createDataKey="createFourthAttribute" stepKey="deleteFourthAttribute"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Edit the product and set those attributes values --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontFotoramaArrowsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontFotoramaArrowsTest.xml index 1a8e0c95a304c..120fa30832075 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontFotoramaArrowsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontFotoramaArrowsTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> </after> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml index db693b7229b17..feefcf6f4559d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml @@ -28,7 +28,10 @@ </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml index d7f98c4cdd307..3b6284a6f6efa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml @@ -32,7 +32,10 @@ <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createSimpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml index 8637de9711da0..a8ab4cca1ac78 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductCustomOptionsDifferentStoreViewsTest.xml @@ -69,7 +69,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> </after> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml index c0653d9dbba7e..066337bf25cb6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsTest.xml @@ -36,7 +36,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderListingFilters"/> - <actionGroup ref="logout" stepKey="logoutAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdmin"/> <!-- Logout customer --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> </after> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml index 7a667ce9667d4..36a803b03199b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptionsWithLongValuesTitle.xml @@ -37,7 +37,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login Customer Storefront --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml index 3e887a0a83aa4..59f0b2f5dd76e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontSpecialPriceForDifferentTimezonesForWebsitesTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Set timezone for default config--> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml index e91f9742b2841..4b5689e6b2720 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml @@ -55,8 +55,8 @@ <argument name="categoryName" value="$$categoryN.name$$, $$categoryM.name$$"/> </actionGroup> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" arguments="full_page" stepKey="flushCache"/> + <wait stepKey="waitBeforeRunCronIndex" time="30"/> + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> <!-- Change "Category Products" and "Product Categories" indexers to "Update on Save" mode --> @@ -72,7 +72,7 @@ <deleteData createDataKey="categoryL" stepKey="deleteCategoryL"/> <deleteData createDataKey="categoryK" stepKey="deleteCategoryK"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open categories K, L, M, N on Storefront --> @@ -138,9 +138,9 @@ <amOnPage url="{{StorefrontCategoryPage.url($$categoryK.custom_attributes[url_key]$$/$$categoryN.custom_attributes[url_key]$$)}}" stepKey="amOnCategoryN"/> <see userInput="$$productC.name$$" selector="{{StorefrontCategoryMainSection.productName}}" stepKey="seeProductInCategoryN"/> - <!-- Run cron twice --> - <magentoCLI command="cron:run" stepKey="runCron"/> - <magentoCLI command="cron:run" stepKey="runCronAgain"/> + <!-- Run cron --> + <wait stepKey="waitBeforeRunMagentoCron" time="30"/> + <magentoCLI stepKey="runMagentoCron" command="cron:run --group=index"/> <!-- Open categories K, L, M, N on Storefront in order to make sure that new assigments are applied --> <!-- Category K contains only Products A, C --> @@ -199,9 +199,9 @@ <amOnPage url="{{StorefrontCategoryPage.url($$categoryK.custom_attributes[url_key]$$/$$categoryN.custom_attributes[url_key]$$)}}" stepKey="onStorefrontCategoryN"/> <see userInput="$$productC.name$$" selector="{{StorefrontCategoryMainSection.productName}}" stepKey="productCOnCategoryN"/> - <!-- Run cron twice --> - <magentoCLI command="cron:run" stepKey="firstCronRun"/> - <magentoCLI command="cron:run" stepKey="secondCronRun"/> + <!-- Run Cron once to reindex product changes --> + <wait stepKey="waitBeforeRunCronIndexAfterProductAssignToCategory" time="30"/> + <magentoCLI stepKey="runCronIndexAfterProductAssignToCategory" command="cron:run --group=index"/> <!-- Open categories K, L, M, N on Storefront in order to make sure that new assigments are applied --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyChildCategoriesShouldNotIncludeInMenuTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyChildCategoriesShouldNotIncludeInMenuTest.xml index d39d54400279c..2a6a05c8ffeab 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyChildCategoriesShouldNotIncludeInMenuTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyChildCategoriesShouldNotIncludeInMenuTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> <argument name="categoryEntity" value="SimpleSubCategory"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <amOnPage url="{{AdminCategoryPage.url}}" stepKey="navigateToCategoryPage1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyDefaultWYSIWYGToolbarOnProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyDefaultWYSIWYGToolbarOnProductTest.xml index fe0ed32f39e1e..8c10f22b7b09e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyDefaultWYSIWYGToolbarOnProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyDefaultWYSIWYGToolbarOnProductTest.xml @@ -19,7 +19,7 @@ <testCaseId value="MAGETWO-80505"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -44,7 +44,7 @@ <seeElement selector="{{ProductDescriptionWYSIWYGToolbarSection.SpecialCharacter}}" stepKey="assertInfo14"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> <test name="Verifydefaultcontrolsonproductshortdescription"> @@ -58,7 +58,7 @@ <testCaseId value="MAGETWO-80505"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -83,7 +83,7 @@ <seeElement selector="{{ProductShortDescriptionWYSIWYGToolbarSection.SpecialCharacter}}" stepKey="assertInfo28"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCatalogTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCatalogTest.xml index cc69d0828015f..b439223674b60 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCatalogTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCatalogTest.xml @@ -19,7 +19,7 @@ <testCaseId value="MAGETWO-82551"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -46,7 +46,7 @@ <see userInput="Hello World!" selector="{{StorefrontCategoryMainSection.CatalogDescription}}" stepKey="assertCatalogDescription"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnProductTest.xml index 5a2728b6532c8..1e4adedfc168d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnProductTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MAGETWO-81819"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -59,7 +59,7 @@ <see userInput="Hello World! Short Content" selector="{{StorefrontProductInfoMainSection.productShortDescription}}" stepKey="assertProductShortDescription"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageFactoryTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageFactoryTest.php index 95b06e40602bf..9a15a5c6c7243 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageFactoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ImageFactoryTest.php @@ -95,6 +95,7 @@ public function createDataProvider(): array return [ $this->getTestDataWithoutAttributes(), $this->getTestDataWithAttributes(), + $this->getTestDataWithoutDimensions() ]; } @@ -209,4 +210,21 @@ private function getTestDataWithAttributes(): array ], ]; } + + /** + * @return array + */ + private function getTestDataWithoutDimensions(): array + { + $data = $this->getTestDataWithoutAttributes(); + + $data['data']['imageParamsBuilder']['image_width'] = null; + $data['data']['imageParamsBuilder']['image_height'] = null; + + $data['expected']['data']['width'] = null; + $data['expected']['data']['height'] = null; + $data['expected']['data']['ratio'] = 1.0; + + return $data; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index b42262f1f0384..909b952078b58 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -6,40 +6,74 @@ namespace Magento\Catalog\Test\Unit\Model; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryProductLinkInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\CategoryLinkRepository; +use Magento\Catalog\Model\Product as ProductModel; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Test for \Magento\Catalog\Model\CategoryLinkRepository + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Model\CategoryLinkRepository + * @var CategoryLinkRepository */ - protected $model; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryRepositoryInterface|MockObject */ - protected $categoryRepositoryMock; + private $categoryRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|MockObject */ - protected $productRepositoryMock; + private $productRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryProductLinkInterface|MockObject */ - protected $productLinkMock; + private $productLinkMock; + /** + * @var Product|MockObject + */ + private $productResourceMock; + + /** + * Initialize required data + */ protected function setUp() { - $this->categoryRepositoryMock = $this->createMock(\Magento\Catalog\Api\CategoryRepositoryInterface::class); - $this->productRepositoryMock = $this->createMock(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $this->productLinkMock = $this->createMock(\Magento\Catalog\Api\Data\CategoryProductLinkInterface::class); - $this->model = new \Magento\Catalog\Model\CategoryLinkRepository( + $this->productResourceMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getProductsIdsBySkus']) + ->getMock(); + $this->categoryRepositoryMock = $this->createMock(CategoryRepositoryInterface::class); + $this->productRepositoryMock = $this->createMock(ProductRepositoryInterface::class); + $this->productLinkMock = $this->createMock(CategoryProductLinkInterface::class); + $this->model = new CategoryLinkRepository( $this->categoryRepositoryMock, - $this->productRepositoryMock + $this->productRepositoryMock, + $this->productResourceMock ); } - public function testSave() + /** + * Assign a product to the category + * + * @return void + */ + public function testSave(): void { $categoryId = 42; $productId = 55; @@ -47,10 +81,10 @@ public function testSave() $sku = 'testSku'; $productPositions = [$productId => $productPosition]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getPostedProducts', 'getProductsPosition', 'setPostedProducts', 'save'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($sku); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -61,14 +95,16 @@ public function testSave() $this->productLinkMock->expects($this->once())->method('getPosition')->willReturn($productPosition); $categoryMock->expects($this->once())->method('setPostedProducts')->with($productPositions); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->save($this->productLinkMock)); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save product "55" with position 1 to category 42 + * Assign a product to the category with `CouldNotSaveException` + * + * @return void */ - public function testSaveWithCouldNotSaveException() + public function testSaveWithCouldNotSaveException(): void { $categoryId = 42; $productId = 55; @@ -76,10 +112,10 @@ public function testSaveWithCouldNotSaveException() $sku = 'testSku'; $productPositions = [$productId => $productPosition]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($sku); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -91,20 +127,28 @@ public function testSaveWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with($productPositions); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); + $this->expectException(CouldNotSaveException::class); $this->model->save($this->productLinkMock); } - public function testDeleteByIds() + /** + * Remove the product assignment from the category + * + * @return void + */ + public function testDeleteByIds(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -113,24 +157,26 @@ public function testDeleteByIds() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->deleteByIds($categoryId, $productSku)); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save product "55" with position 1 to category 42 + * Delete the product assignment from the category with `CouldNotSaveException` + * + * @return void */ - public function testDeleteByIdsWithCouldNotSaveException() + public function testDeleteByIdsWithCouldNotSaveException(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -140,50 +186,61 @@ public function testDeleteByIdsWithCouldNotSaveException() $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); + $this->expectException(CouldNotSaveException::class); $this->model->deleteByIds($categoryId, $productSku); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The category doesn't contain the specified product. + * Delete the product assignment from the category with `InputException` + * + * @return void */ - public function testDeleteWithInputException() + public function testDeleteWithInputException(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 60; $productPositions = [55 => 1]; $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($productSku); $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) ->willReturn($productMock); $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); $productMock->expects($this->once())->method('getId')->willReturn($productId); - $categoryMock->expects($this->never())->method('save'); + + $this->expectExceptionMessage('The category doesn\'t contain the specified product.'); + $this->expectException(InputException::class); $this->assertTrue($this->model->delete($this->productLinkMock)); } - public function testDelete() + /** + * Delete the product assignment from the category + * + * @return void + */ + public function testDelete(): void { - $categoryId = "42"; - $productSku = "testSku"; + $categoryId = 42; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $this->productLinkMock->expects($this->once())->method('getCategoryId')->willReturn($categoryId); $this->productLinkMock->expects($this->once())->method('getSku')->willReturn($productSku); $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); - $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + $productMock = $this->createMock(ProductModel::class); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) @@ -192,6 +249,82 @@ public function testDelete() $productMock->expects($this->once())->method('getId')->willReturn($productId); $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); $categoryMock->expects($this->once())->method('save'); + $this->assertTrue($this->model->delete($this->productLinkMock)); } + + /** + * Delete by products skus + * + * @return void + */ + public function testDeleteBySkus(): void + { + $categoryId = 42; + $productSkus = ['testSku', 'testSku1', 'testSku2', 'testSku3']; + $productPositions = [55 => 1, 56 => 2, 57 => 3, 58 => 4]; + $categoryMock = $this->createPartialMock( + Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') + ->willReturn(['testSku' => 55, 'testSku1' => 56, 'testSku2' => 57, 'testSku3' => 58]); + $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); + $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); + $categoryMock->expects($this->once())->method('save'); + + $this->assertTrue($this->model->deleteBySkus($categoryId, $productSkus)); + } + + /** + * Delete by products skus with `InputException` + * + * @return void + */ + public function testDeleteBySkusWithInputException(): void + { + $categoryId = 42; + $productSku = 'testSku'; + $categoryMock = $this->createPartialMock( + Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + + $this->expectExceptionMessage('The category doesn\'t contain the specified products.'); + $this->expectException(InputException::class); + $this->model->deleteBySkus($categoryId, [$productSku]); + } + + /** + * Delete by products skus with `CouldNotSaveException` + * + * @return void + */ + public function testDeleteSkusIdsWithCouldNotSaveException(): void + { + $categoryId = 42; + $productSku = 'testSku'; + $productId = 55; + $productPositions = [55 => 1]; + $categoryMock = $this->createPartialMock( + Category::class, + ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] + ); + $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) + ->willReturn($categoryMock); + $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') + ->willReturn(['testSku' => $productId]); + $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productPositions); + $categoryMock->expects($this->once())->method('setPostedProducts')->with([]); + $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); + $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); + + $this->expectExceptionMessage('Could not save products "testSku" to category 42'); + $this->expectException(CouldNotSaveException::class); + $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php index b72ecbf195d39..91441890e83b1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -3,77 +3,91 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Test\Unit\Model\Product; +use Magento\Catalog\Api\Data\ProductExtension; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Attribute\ScopeOverriddenValue; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Catalog\Model\Product\Copier; +use Magento\Catalog\Model\Product\CopyConstructorInterface; +use Magento\Catalog\Model\Product\Option\Repository; +use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Model\ResourceModel\Product as ProductResourceModel; +use Magento\CatalogInventory\Api\Data\StockItemInterface; +use Magento\Eav\Model\Entity\AbstractEntity; +use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; +use Magento\Framework\EntityManager\EntityMetadata; +use Magento\Framework\EntityManager\MetadataPool; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** * Test for Magento\Catalog\Model\Product\Copier class. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CopierTest extends \PHPUnit\Framework\TestCase +class CopierTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Copier */ - private $optionRepositoryMock; + private $_model; /** - * @var Copier + * @var Repository|MockObject */ - private $_model; + private $optionRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CopyConstructorInterface|MockObject */ private $copyConstructorMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductFactory|MockObject */ private $productFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ScopeOverriddenValue|MockObject */ private $scopeOverriddenValueMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ private $productMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EntityMetadata|MockObject */ private $metadata; + /** + * @ingeritdoc + */ protected function setUp() { - $this->copyConstructorMock = $this->createMock(\Magento\Catalog\Model\Product\CopyConstructorInterface::class); - $this->productFactoryMock = $this->createPartialMock( - \Magento\Catalog\Model\ProductFactory::class, - ['create'] - ); - $this->scopeOverriddenValueMock = $this->createMock( - \Magento\Catalog\Model\Attribute\ScopeOverriddenValue::class - ); - $this->optionRepositoryMock = $this->createMock( - \Magento\Catalog\Model\Product\Option\Repository::class - ); + $this->copyConstructorMock = $this->createMock(CopyConstructorInterface::class); + $this->productFactoryMock = $this->createPartialMock(ProductFactory::class, ['create']); + $this->scopeOverriddenValueMock = $this->createMock(ScopeOverriddenValue::class); + $this->optionRepositoryMock = $this->createMock(Repository::class); $this->productMock = $this->createMock(Product::class); - $this->productMock->expects($this->any())->method('getEntityId')->willReturn(1); - $this->metadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadata::class) + $this->metadata = $this->getMockBuilder(EntityMetadata::class) ->disableOriginalConstructor() ->getMock(); - $metadataPool = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class) + + /** @var MetadataPool|MockObject $metadataPool */ + $metadataPool = $this->getMockBuilder(MetadataPool::class) ->disableOriginalConstructor() ->getMock(); - $metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata); + $metadataPool->expects($this->once()) + ->method('getMetadata') + ->willReturn($this->metadata); $this->_model = new Copier( $this->copyConstructorMock, $this->productFactoryMock, @@ -84,13 +98,15 @@ protected function setUp() } /** + * Test duplicate product + * + * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testCopy() + public function testCopy(): void { - $stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class) - ->getMock(); - $extensionAttributes = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class) + $stockItem = $this->createMock(StockItemInterface::class); + $extensionAttributes = $this->getMockBuilder(ProductExtension::class) ->setMethods(['getStockItem', 'setData']) ->getMock(); $extensionAttributes @@ -106,15 +122,19 @@ public function testCopy() 'product data' => ['product data'], ProductInterface::EXTENSION_ATTRIBUTES_KEY => $extensionAttributes, ]; - $this->productMock->expects($this->atLeastOnce())->method('getWebsiteIds'); - $this->productMock->expects($this->atLeastOnce())->method('getCategoryIds'); - $this->productMock->expects($this->any())->method('getData')->willReturnMap([ - ['', null, $productData], - ['linkField', null, '1'], - ]); + $this->productMock->expects($this->atLeastOnce()) + ->method('getWebsiteIds'); + $this->productMock->expects($this->atLeastOnce()) + ->method('getCategoryIds'); + $this->productMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap([ + ['', null, $productData], + ['linkField', null, '1'], + ]); $entityMock = $this->getMockForAbstractClass( - \Magento\Eav\Model\Entity\AbstractEntity::class, + AbstractEntity::class, [], '', false, @@ -122,12 +142,12 @@ public function testCopy() true, ['checkAttributeUniqueValue'] ); - $entityMock->expects($this->any()) + $entityMock->expects($this->once()) ->method('checkAttributeUniqueValue') ->willReturn(true); $attributeMock = $this->getMockForAbstractClass( - \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, + AbstractAttribute::class, [], '', false, @@ -135,22 +155,24 @@ public function testCopy() true, ['getEntity'] ); - $attributeMock->expects($this->any()) + $attributeMock->expects($this->once()) ->method('getEntity') ->willReturn($entityMock); - $resourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + $resourceMock = $this->getMockBuilder(ProductResourceModel::class) ->disableOriginalConstructor() ->setMethods(['getAttributeRawValue', 'duplicate', 'getAttribute']) ->getMock(); - $resourceMock->expects($this->any()) + $resourceMock->expects($this->once()) ->method('getAttributeRawValue') ->willReturn('urk-key-1'); - $resourceMock->expects($this->any()) + $resourceMock->expects($this->exactly(2)) ->method('getAttribute') ->willReturn($attributeMock); - $this->productMock->expects($this->any())->method('getResource')->will($this->returnValue($resourceMock)); + $this->productMock->expects($this->exactly(2)) + ->method('getResource') + ->willReturn($resourceMock); $duplicateMock = $this->createPartialMock( Product::class, @@ -170,51 +192,77 @@ public function testCopy() 'setUrlKey', 'setStoreId', 'getStoreIds', + 'setMetaTitle', + 'setMetaKeyword', + 'setMetaDescription', ] ); - $this->productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($duplicateMock)); + $this->productFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($duplicateMock); $duplicateMock->expects($this->once())->method('setOptions')->with([]); $duplicateMock->expects($this->once())->method('setIsDuplicate')->with(true); $duplicateMock->expects($this->once())->method('setOriginalLinkId')->with(1); - $duplicateMock->expects( - $this->once() - )->method( - 'setStatus' - )->with( - \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED - ); + $duplicateMock->expects($this->once()) + ->method('setStatus') + ->with(Status::STATUS_DISABLED); $duplicateMock->expects($this->atLeastOnce())->method('setStoreId'); - $duplicateMock->expects($this->once())->method('setCreatedAt')->with(null); - $duplicateMock->expects($this->once())->method('setUpdatedAt')->with(null); - $duplicateMock->expects($this->once())->method('setId')->with(null); - $duplicateMock->expects($this->atLeastOnce())->method('getStoreIds')->willReturn([]); - $duplicateMock->expects($this->atLeastOnce())->method('setData')->willReturn($duplicateMock); - $this->copyConstructorMock->expects($this->once())->method('build')->with($this->productMock, $duplicateMock); - $duplicateMock->expects($this->once())->method('setUrlKey')->with('urk-key-2')->willReturn($duplicateMock); - $duplicateMock->expects($this->once())->method('save'); - - $this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField'); - - $duplicateMock->expects($this->any())->method('getData')->willReturnMap([ - ['linkField', null, '2'], - ]); + $duplicateMock->expects($this->once()) + ->method('setCreatedAt') + ->with(null); + $duplicateMock->expects($this->once()) + ->method('setUpdatedAt') + ->with(null); + $duplicateMock->expects($this->once()) + ->method('setId') + ->with(null); + $duplicateMock->expects($this->once()) + ->method('setMetaTitle') + ->with(null); + $duplicateMock->expects($this->once()) + ->method('setMetaKeyword') + ->with(null); + $duplicateMock->expects($this->once()) + ->method('setMetaDescription') + ->with(null); + $duplicateMock->expects($this->atLeastOnce()) + ->method('getStoreIds')->willReturn([]); + $duplicateMock->expects($this->atLeastOnce()) + ->method('setData') + ->willReturn($duplicateMock); + $this->copyConstructorMock->expects($this->once()) + ->method('build') + ->with($this->productMock, $duplicateMock); + $duplicateMock->expects($this->once()) + ->method('setUrlKey') + ->with('urk-key-2') + ->willReturn($duplicateMock); + $duplicateMock->expects($this->once()) + ->method('save'); + $this->metadata->expects($this->once()) + ->method('getLinkField') + ->willReturn('linkField'); + $duplicateMock->expects($this->never()) + ->method('getData'); $this->optionRepositoryMock->expects($this->once()) ->method('duplicate') ->with($this->productMock, $duplicateMock); - $resourceMock->expects($this->once())->method('duplicate')->with(1, 2); $this->assertEquals($duplicateMock, $this->_model->copy($this->productMock)); } /** + * Test duplicate product with `UrlAlreadyExistsException` while copy stores url + * + * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl() + public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void { - $stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class) + $stockItem = $this->getMockBuilder(StockItemInterface::class) ->getMock(); - $extensionAttributes = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class) + $extensionAttributes = $this->getMockBuilder(ProductExtension::class) ->setMethods(['getStockItem', 'setData']) ->getMock(); $extensionAttributes diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductFrontendAction/SynchronizerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductFrontendAction/SynchronizerTest.php index 38bed83cb9504..8b70899cd26d3 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductFrontendAction/SynchronizerTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductFrontendAction/SynchronizerTest.php @@ -82,15 +82,15 @@ public function testFilterProductActions() { $typeId = 'recently_compared_product'; $productsData = [ - 1 => [ + 'website-1-1' => [ 'added_at' => 12, 'product_id' => 1, ], - 2 => [ + 'website-1-2' => [ 'added_at' => 13, 'product_id' => '2', ], - 3 => [ + 'website-2-3' => [ 'added_at' => 14, 'product_id' => 3, ] diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Webapi/ProductOutputProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Webapi/ProductOutputProcessorTest.php new file mode 100644 index 0000000000000..fa419d23626ae --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Webapi/ProductOutputProcessorTest.php @@ -0,0 +1,350 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Unit\Model\Product\Webapi; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product\Webapi\ProductOutputProcessor; +use Magento\Framework\Webapi\Request; +use Magento\Framework\Webapi\Rest\Request\DeserializerInterface; + +class ProductOutputProcessorTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Request + */ + private $requestMock; + + /** + * @var DeserializerInterface + */ + private $deserializerMock; + + /** + * @var ProductOutputProcessor + */ + private $productOutputProcessor; + + protected function setUp() + { + $this->requestMock = $this->createPartialMock( + Request::class, + ['getContent'] + ); + $this->deserializerMock = $this->getMockBuilder(DeserializerInterface::class) + ->getMockForAbstractClass(); + $this->productOutputProcessor = new ProductOutputProcessor($this->requestMock, $this->deserializerMock); + } + + /** + * @dataProvider getProductProcessorDataProvider + * @param $request + * @param $product + * @param $result + * @param $expectedResult + */ + public function testGetByProductType( + array $request, + ProductInterface $product, + array $result, + array $expectedResult + ) { + $this->requestMock + ->method('getContent') + ->willReturn($request); + $this->deserializerMock + ->method('deserialize') + ->willReturn($request); + $this->assertEquals($expectedResult, $this->productOutputProcessor->execute($product, $result)); + } + + /** + * Product data provider + * + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function getProductProcessorDataProvider() + { + return [ + 'request object contains `product_links` and `tier_prices`' => [ + 'request' => [ + [ + 'product' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ], + 'request object contains `product_links`' => [ + 'request' => [ + [ + 'product' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [] + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [] + ] + ], + 'request object SKU does not match with product object SKU' => [ + 'request' => [ + [ + 'product' => [ + 'sku' => 'MH01', + 'status' => 1 + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH03', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ], + 'request object does not contain `sku`' => [ + 'request' => [ + [ + 'product' => [ + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ], + 'request object has empty product' => [ + 'request' => [ + [ + 'product' => [] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ], + 'request object does not contain product' => [ + 'request' => [ + [ + 'order' => [ + 'order_id' => 1, + 'order_details' => 'test' + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ], + 'request object contains `product_links` is null and `tier_prices` is null' => [ + 'request' => [ + [ + 'product' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => null, + 'tier_prices' => null + ] + ] + ], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => null, + 'tier_prices' => null + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => null, + 'tier_prices' => null + ] + ], + 'request object has empty array' => [ + 'request' => [], + 'product' => $this->setProductInformation( + [ + 'sku' => 'MH01', + 'status' => 1, + 'product_links' => [], + 'tier_prices' => [] + ] + ), + 'result' => [ + 'sku' => 'MH01', + 'status' => 1 + ], + 'expectedResult' => [ + 'sku' => 'MH01', + 'status' => 1 + ] + ] + ]; + } + + private function setProductInformation($productArr) + { + $productMock = $this->getMockBuilder(ProductInterface::class) + ->disableOriginalConstructor() + ->setMethods( + [ + 'setSku', + 'setStatus', + 'setProductLinks', + 'setTierPrices', + 'getSku', + 'getProductLinks', + 'getTierPrices' + ] + ) + ->getMockForAbstractClass(); + $productMock + ->method('setSku') + ->with($productArr['sku']) + ->willReturn(true); + $productMock + ->method('getSku') + ->willReturn($productArr['sku']); + $productMock + ->method('setStatus') + ->with($productArr['status']) + ->willReturn(true); + $productMock + ->method('setProductLinks') + ->with($productArr['product_links']) + ->willReturn(true); + $productMock + ->method('getProductLinks') + ->willReturn($productArr['product_links']); + $productMock + ->method('setTierPrices') + ->with($productArr['tier_prices']) + ->willReturn(true); + $productMock + ->method('getTierPrices') + ->willReturn($productArr['tier_prices']); + return $productMock; + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php index ab52d87f56291..69bd7dc059022 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php @@ -7,45 +7,66 @@ namespace Magento\Catalog\Test\Unit\Model\ProductLink; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Catalog\Model\ProductLink\Management; +use Magento\Catalog\Model\ProductRepository; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\LinkTypeProvider; +use Magento\Catalog\Model\ProductLink\Link; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; -class ManagementTest extends \PHPUnit\Framework\TestCase +/** + * Unit Test for Magento\Catalog\Model\ProductLink\Management + */ +class ManagementTest extends TestCase { + + const STUB_PRODUCT_SKU_1 = 'Simple Product 1'; + const STUB_PRODUCT_SKU_2 = 'Simple Product 2'; + const STUB_PRODUCT_TYPE = 'simple'; + const STUB_LINK_TYPE = 'related'; + const STUB_BAD_TYPE = 'bad type'; + /** - * @var \Magento\Catalog\Model\ProductLink\Management + * @var Management */ protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductRepository|MockObject */ - protected $productRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ protected $productMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var LinkTypeProvider|MockObject */ protected $linkTypeProviderMock; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerHelper */ protected $objectManager; - protected function setUp() + /** + * @inheritDoc + */ + protected function setUp(): void { - $this->productRepositoryMock = $this->createMock(\Magento\Catalog\Model\ProductRepository::class); - $this->productMock = $this->createMock(\Magento\Catalog\Model\Product::class); - - $this->linkTypeProviderMock = $this->createMock(\Magento\Catalog\Model\Product\LinkTypeProvider::class); + $this->productRepositoryMock = $this->createMock(ProductRepository::class); + $this->productMock = $this->createMock(Product::class); + $this->linkTypeProviderMock = $this->createMock(LinkTypeProvider::class); - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManager = new ObjectManagerHelper($this); $this->model = $this->objectManager->getObject( - \Magento\Catalog\Model\ProductLink\Management::class, + Management::class, [ 'productRepository' => $this->productRepositoryMock, 'linkTypeProvider' => $this->linkTypeProviderMock @@ -53,193 +74,320 @@ protected function setUp() ); } - public function testGetLinkedItemsByType() + /** + * Test getLinkedItemsByType() + * + * @return void + */ + public function testGetLinkedItemsByType(): void { - $productSku = 'Simple Product 1'; - $linkType = 'related'; - $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_LINK_TYPE; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) ->willReturn($this->productMock); - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "Simple Product 2"); - $inputRelatedLink->setData("type_id", "simple"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); + + $this->productMock->expects($this->once()) + ->method('getProductLinks') + ->willReturn($links); - $this->productMock->expects($this->once())->method('getProductLinks')->willReturn($links); - $this->assertEquals($links, $this->model->getLinkedItemsByType($productSku, $linkType)); + $this->assertEquals( + $links, + $this->model->getLinkedItemsByType($productSku, $linkType) + ); } /** - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage The "bad type" link type is unknown. Verify the type and try again. + * Test for GetLinkedItemsByType() with wrong type + * + * @return void + * @throws NoSuchEntityException */ - public function testGetLinkedItemsByTypeWithWrongType() + public function testGetLinkedItemsByTypeWithWrongType(): void { - $productSku = 'Simple Product 1'; - $linkType = 'bad type'; - $this->productRepositoryMock->expects($this->never())->method('get')->with($productSku) + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_BAD_TYPE; + + $this->productRepositoryMock->expects($this->never()) + ->method('get') + ->with($productSku) ->willReturn($this->productMock); - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "Simple Product 2"); - $inputRelatedLink->setData("type_id", "simple"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); + + $this->productMock->expects($this->never()) + ->method('getProductLinks') + ->willReturn($links); + + $this->expectException(NoSuchEntityException::class); + $this->expectExceptionMessage( + 'The "bad type" link type is unknown. Verify the type and try again.' + ); - $this->productMock->expects($this->never())->method('getProductLinks')->willReturn($links); $this->model->getLinkedItemsByType($productSku, $linkType); } - public function testSetProductLinks() + /** + * Test for setProductLinks() + * + * @return void + */ + public function testSetProductLinks(): void { - $productSku = 'Simple Product 1'; - $linkType = 'related'; - $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_LINK_TYPE; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) ->willReturn($this->productMock); - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "Simple Product 1"); - $inputRelatedLink->setData("type_id", "related"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); + + $this->productMock->expects($this->once()) + ->method('getProductLinks') + ->willReturn([]); + $this->productMock->expects($this->once()) + ->method('setProductLinks') + ->with($links); - $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); - $this->productMock->expects($this->once())->method('setProductLinks')->with($links); $this->assertTrue($this->model->setProductLinks($productSku, $links)); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage "linkType" is required. Enter and try again. + * Test for SetProductLinks without link type in link object + * + * @return void + * @throws InputException */ - public function testSetProductLinksWithoutLinkTypeInLink() + public function testSetProductLinksWithoutLinkTypeInLink(): void { - $productSku = 'Simple Product 1'; + $productSku = self::STUB_PRODUCT_SKU_1; - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); + $inputRelatedLink = $this->objectManager->getObject(Link::class); $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setData("sku", "Simple Product 1"); + $inputRelatedLink->setData("sku", self::STUB_PRODUCT_SKU_2); $inputRelatedLink->setPosition(0); $links = [$inputRelatedLink]; - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); + + $this->expectException(InputException::class); + $this->expectExceptionMessage( + '"linkType" is required. Enter and try again.' + ); $this->assertTrue($this->model->setProductLinks($productSku, $links)); } /** - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage The "bad type" link type wasn't found. Verify the type and try again. + * Test for SetProductLinks with empty array of items + * + * @return void + * @throws InputException + */ + public function testSetProductLinksWithEmptyArrayItems(): void + { + $productSku = self::STUB_PRODUCT_SKU_1; + + $this->productRepositoryMock->expects($this->never()) + ->method('get') + ->with($productSku) + ->willReturn($this->productMock); + + $this->linkTypeProviderMock->expects($this->never()) + ->method('getLinkTypes') + ->willReturn([]); + + $this->expectException(InputException::class); + $this->expectExceptionMessage( + 'Invalid value of "empty array" provided for the items field.' + ); + + $this->assertTrue($this->model->setProductLinks($productSku, [])); + } + + /** + * Test setProductLinks() throw exception if product link type not exist + * + * @return void + * @throws NoSuchEntityException */ public function testSetProductLinksThrowExceptionIfProductLinkTypeDoesNotExist() { - $productSku = 'Simple Product 1'; - $linkType = 'bad type'; - $this->productRepositoryMock->expects($this->never())->method('get')->with($productSku) + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_BAD_TYPE; + + $this->productRepositoryMock->expects($this->never()) + ->method('get') + ->with($productSku) ->willReturn($this->productMock); - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "Simple Product 2"); - $inputRelatedLink->setData("type_id", "simple"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); + + $this->expectException(NoSuchEntityException::class); + $this->expectExceptionMessage( + 'The "bad type" link type wasn\'t found. Verify the type and try again.' + ); $this->assertTrue($this->model->setProductLinks('', $links)); } /** - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again. + * Test for setProductLinks() with no product exception + * + * @return void + * @throws NoSuchEntityException */ public function testSetProductLinksNoProductException() { - $productSku = 'Simple Product 1'; - $linkType = 'related'; - - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "Simple Product 2"); - $inputRelatedLink->setData("type_id", "simple"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_LINK_TYPE; + + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; - $this->linkTypeProviderMock->expects($this->once()) - ->method('getLinkTypes') - ->willReturn($linkTypes); + $this->getLinkTypesMock(); $this->productRepositoryMock->expects($this->once()) ->method('get') - ->will( - $this->throwException( - new \Magento\Framework\Exception\NoSuchEntityException( - __("The product that was requested doesn't exist. Verify the product and try again.") - ) + ->willThrowException( + new NoSuchEntityException( + __("The product that was requested doesn't exist. Verify the product and try again.") ) ); + + $this->expectException(NoSuchEntityException::class); + $this->expectExceptionMessage( + "The product that was requested doesn't exist. Verify the product and try again." + ); + $this->model->setProductLinks($productSku, $links); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage The linked products data is invalid. Verify the data and try again. + * Test setProductLnks() with invliad data exception + * + * @return void + * @throws CouldNotSaveException */ - public function testSetProductLinksInvalidDataException() + public function testSetProductLinksInvalidDataException(): void { - $productSku = 'Simple Product 1'; - $linkType = 'related'; - $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) + $productSku = self::STUB_PRODUCT_SKU_1; + $linkType = self::STUB_LINK_TYPE; + + $this->productRepositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) ->willReturn($this->productMock); - $inputRelatedLink = $this->objectManager->getObject(\Magento\Catalog\Model\ProductLink\Link::class); - $inputRelatedLink->setProductSku($productSku); - $inputRelatedLink->setLinkType($linkType); - $inputRelatedLink->setData("sku", "bad sku"); - $inputRelatedLink->setData("type_id", "bad type"); - $inputRelatedLink->setPosition(0); - $links = [$inputRelatedLink]; + $links = $this->getInputRelatedLinkMock( + $productSku, + $linkType, + self::STUB_PRODUCT_SKU_2, + self::STUB_PRODUCT_TYPE + ); + + $this->getLinkTypesMock(); + + $this->productMock->expects($this->once()) + ->method('getProductLinks') + ->willReturn([]); + + $this->productRepositoryMock->expects($this->once()) + ->method('save') + ->willThrowException( + new CouldNotSaveException( + __("The linked products data is invalid. Verify the data and try again.") + ) + ); + + $this->expectException(CouldNotSaveException::class); + $this->expectExceptionMessage( + "The linked products data is invalid. Verify the data and try again." + ); + + $this->model->setProductLinks($productSku, $links); + } + + /** + * Mock for getLinkTypesMock + * + * @return void + */ + private function getLinkTypesMock(): void + { + $linkTypes = [ + 'related' => 1, + 'upsell' => 4, + 'crosssell' => 5, + 'associated' => 3 + ]; - $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; $this->linkTypeProviderMock->expects($this->once()) ->method('getLinkTypes') ->willReturn($linkTypes); + } - $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); - - $this->productRepositoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); - $this->model->setProductLinks($productSku, $links); + /** + * get inputRelatedLinkMock + * + * @param string $productSku1 + * @param string $linkType + * @param string $productSku2 + * @param string $typeId + * @return array + */ + private function getInputRelatedLinkMock( + string $productSku1, + string $linkType, + string $productSku2, + string $typeId + ) { + + $inputRelatedLinkMock = $this->objectManager->getObject(Link::class); + $inputRelatedLinkMock->setProductSku($productSku1); + $inputRelatedLinkMock->setLinkType($linkType); + $inputRelatedLinkMock->setData("sku", $productSku2); + $inputRelatedLinkMock->setData("type_id", $typeId); + $inputRelatedLinkMock->setPosition(0); + + return [$inputRelatedLinkMock]; } } diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/SetSpecialPriceStartDateTest.php b/app/code/Magento/Catalog/Test/Unit/Observer/SetSpecialPriceStartDateTest.php new file mode 100644 index 0000000000000..c44a64f1d7433 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Observer/SetSpecialPriceStartDateTest.php @@ -0,0 +1,135 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Catalog\Test\Unit\Observer; + +use Magento\Catalog\Model\Product; +use Magento\Catalog\Observer\SetSpecialPriceStartDate; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\Stdlib\DateTime\Timezone; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Catalog\Observer\SetSpecialPriceStartDate + */ +class SetSpecialPriceStartDateTest extends TestCase +{ + /** + * Testable Object + * + * @var SetSpecialPriceStartDate + */ + private $observer; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * @var Product|MockObject + */ + private $productMock; + + /** + * @var Timezone|MockObject + */ + private $timezone; + + /** + * @var \DateTime|MockObject + */ + private $dateObject; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + $this->timezone = $this->createMock(Timezone::class); + $this->dateObject = $this->createMock(\DateTime::class); + + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getProduct']) + ->getMock(); + + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getSpecialPrice', 'getSpecialFromDate', 'setData']) + ->getMock(); + + $this->observer = $this->objectManager->getObject( + SetSpecialPriceStartDate::class, + [ + 'localeDate' => $this->timezone + ] + ); + } + + /** + * Test observer execute method + */ + public function testExecuteModifySpecialFromDate(): void + { + $specialPrice = 15; + $specialFromDate = null; + $localeDateMock = ['special_from_date' => $this->returnValue($this->dateObject)]; + + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->dateObject->expects($this->any()) + ->method('setTime') + ->willReturnSelf(); + + $this->timezone + ->expects($this->once()) + ->method('date') + ->willReturn($this->dateObject); + + $this->productMock + ->expects($this->once()) + ->method('getSpecialPrice') + ->willReturn($specialPrice); + + $this->productMock + ->expects($this->once()) + ->method('getSpecialFromDate') + ->willReturn($specialFromDate); + + $this->productMock + ->expects($this->once()) + ->method('setData') + ->willReturn($localeDateMock); + + $this->observer->execute($this->observerMock); + } +} diff --git a/app/code/Magento/Catalog/ViewModel/Product/Listing/PreparePostData.php b/app/code/Magento/Catalog/ViewModel/Product/Listing/PreparePostData.php new file mode 100644 index 0000000000000..c7ea49cc4dc1b --- /dev/null +++ b/app/code/Magento/Catalog/ViewModel/Product/Listing/PreparePostData.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\ViewModel\Product\Listing; + +use Magento\Framework\View\Element\Block\ArgumentInterface; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\Url\Helper\Data as UrlHelper; + +/** + * Check is available add to compare. + */ +class PreparePostData implements ArgumentInterface +{ + /** + * @var UrlHelper + */ + private $urlHelper; + + /** + * @param UrlHelper $urlHelper + */ + public function __construct(UrlHelper $urlHelper) + { + $this->urlHelper = $urlHelper; + } + + /** + * Wrapper for the PostHelper::getPostData() + * + * @param string $url + * @param array $data + * @return array + */ + public function getPostData(string $url, array $data = []):array + { + if (!isset($data[ActionInterface::PARAM_NAME_URL_ENCODED])) { + $data[ActionInterface::PARAM_NAME_URL_ENCODED] = $this->urlHelper->getEncodedUrl(); + } + return ['action' => $url, 'data' => $data]; + } +} diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index eda6dbd2d9d6f..223d690d28327 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -74,6 +74,7 @@ <preference for="Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface" type="Magento\Catalog\Model\Product\Configuration\Item\ItemResolverComposite" /> <preference for="Magento\Catalog\Api\Data\MassActionInterface" type="\Magento\Catalog\Model\MassAction" /> <preference for="Magento\Catalog\Model\ProductLink\Data\ListCriteriaInterface" type="Magento\Catalog\Model\ProductLink\Data\ListCriteria" /> + <preference for="Magento\Catalog\Api\CategoryListDeleteBySkuInterface" type="Magento\Catalog\Model\CategoryLinkRepository"/> <type name="Magento\Customer\Model\ResourceModel\Visitor"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> diff --git a/app/code/Magento/Catalog/etc/webapi_rest/di.xml b/app/code/Magento/Catalog/etc/webapi_rest/di.xml index bfbc05b12079d..14779245f21af 100644 --- a/app/code/Magento/Catalog/etc/webapi_rest/di.xml +++ b/app/code/Magento/Catalog/etc/webapi_rest/di.xml @@ -28,4 +28,16 @@ <type name="Magento\Catalog\Api\CategoryRepositoryInterface"> <plugin name="category_authorization" type="Magento\Catalog\Plugin\CategoryAuthorization" /> </type> + <type name="Magento\Framework\Reflection\DataObjectProcessor"> + <arguments> + <argument name="processors" xsi:type="array"> + <item name="Magento\Catalog\Model\Product" xsi:type="object">Magento\Catalog\Model\Product\Webapi\ProductOutputProcessor\Proxy</item> + </argument> + </arguments> + </type> + <type name="Magento\Catalog\Model\Product\Webapi\ProductOutputProcessor"> + <arguments> + <argument name="deserializer" xsi:type="object">Magento\Framework\Webapi\Rest\Request\Deserializer\Json</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Catalog/etc/webapi_soap/di.xml b/app/code/Magento/Catalog/etc/webapi_soap/di.xml index bfbc05b12079d..a709f23d8c12b 100644 --- a/app/code/Magento/Catalog/etc/webapi_soap/di.xml +++ b/app/code/Magento/Catalog/etc/webapi_soap/di.xml @@ -28,4 +28,16 @@ <type name="Magento\Catalog\Api\CategoryRepositoryInterface"> <plugin name="category_authorization" type="Magento\Catalog\Plugin\CategoryAuthorization" /> </type> + <type name="Magento\Framework\Reflection\DataObjectProcessor"> + <arguments> + <argument name="processors" xsi:type="array"> + <item name="Magento\Catalog\Model\Product" xsi:type="object">Magento\Catalog\Model\Product\Webapi\ProductOutputProcessor\Proxy</item> + </argument> + </arguments> + </type> + <type name="Magento\Catalog\Model\Product\Webapi\ProductOutputProcessor"> + <arguments> + <argument name="deserializer" xsi:type="object">Magento\Framework\Webapi\Rest\Request\Deserializer\Xml</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml index da0b3b36d561e..89d005a178fac 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/composite/fieldset/options/type/file.phtml @@ -22,7 +22,7 @@ require(['prototype'], function(){ initializeFile: function(inputBox) { this.inputFile = inputBox.select('input[name="<?= /* @noEscape */ $_fileName ?>"]')[0]; this.inputFileAction = inputBox.select('input[name="<?= /* @noEscape */ $_fieldNameAction ?>"]')[0]; - this.fileNameBox = inputBox.up('dd').select('.<?= /* @noEscape */ $_fileNamed ?>')[0]; + this.fileNameBox = inputBox.up('div').select('.<?= /* @noEscape */ $_fileNamed ?>')[0]; }, toggleFileChange: function(inputBox) { diff --git a/app/code/Magento/Catalog/view/base/templates/product/price/tier_prices.phtml b/app/code/Magento/Catalog/view/base/templates/product/price/tier_prices.phtml index 5949b54268a62..af50446c93a95 100644 --- a/app/code/Magento/Catalog/view/base/templates/product/price/tier_prices.phtml +++ b/app/code/Magento/Catalog/view/base/templates/product/price/tier_prices.phtml @@ -17,15 +17,15 @@ $tierPrices = $tierPriceModel->getTierPriceList(); $msrpShowOnGesture = $block->getPriceType('msrp_price')->isShowPriceOnGesture(); $product = $block->getSaleableItem(); ?> -<?php if (count($tierPrices)) : ?> +<?php if (count($tierPrices)): ?> <ul class="<?= $block->escapeHtmlAttr(($block->hasListClass() ? $block->getListClass() : 'prices-tier items')) ?>"> - <?php foreach ($tierPrices as $index => $price) : ?> + <?php foreach ($tierPrices as $index => $price): ?> <li class="item"> <?php $productId = $product->getId(); $isSaleable = $product->isSaleable(); $popupId = 'msrp-popup-' . $productId . $block->getRandomString(20); - if ($msrpShowOnGesture && $price['price']->getValue() < $product->getMsrp()) : + if ($msrpShowOnGesture && $price['price']->getValue() < $product->getMsrp()): $addToCartUrl = ''; if ($isSaleable) { $addToCartUrl = $this->helper(\Magento\Checkout\Helper\Cart::class) @@ -60,7 +60,7 @@ $product = $block->getSaleableItem(); id="<?= $block->escapeHtmlAttr($popupId) ?>" data-tier-price="<?= $block->escapeHtml($block->jsonEncode($tierPriceData)) ?>"> <?= $block->escapeHtml(__('Click for price')) ?></a> - <?php else : + <?php else: $priceAmountBlock = $block->renderAmount( $price['price'], [ @@ -73,11 +73,12 @@ $product = $block->getSaleableItem(); ?> <?= /* @noEscape */ ($block->getShowDetailedPrice() !== false) ? __( - 'Buy %1 for %2 each and <strong class="benefit">save<span class="percent tier-%3"> %4</span>%</strong>', + 'Buy %1 for %2 each and '. + '<strong class="benefit">save<span class="percent tier-%3"> %4</span>%</strong>', $price['price_qty'], $priceAmountBlock, $index, - $block->formatPercent($price['percentage_value'] ?? $tierPriceModel->getSavePercent($price['price'])) + $block->formatPercent($tierPriceModel->getSavePercent($price['price'])) ) : __('Buy %1 for %2 each', $price['price_qty'], $priceAmountBlock); ?> @@ -85,7 +86,7 @@ $product = $block->getSaleableItem(); </li> <?php endforeach; ?> </ul> - <?php if ($msrpShowOnGesture) :?> + <?php if ($msrpShowOnGesture):?> <script type="text/x-magento-init"> { ".product-info-main": { diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml index 13e2d998f6cdd..6e24f84f00482 100644 --- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml @@ -175,6 +175,7 @@ <block class="Magento\Catalog\Block\Product\ProductList\Related" name="catalog.product.related" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">related</argument> + <argument name="view_model" xsi:type="object">Magento\Catalog\ViewModel\Product\Listing\PreparePostData</argument> </arguments> <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="related.product.addto" as="addto"> <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare" @@ -185,6 +186,7 @@ <block class="Magento\Catalog\Block\Product\ProductList\Upsell" name="product.info.upsell" template="Magento_Catalog::product/list/items.phtml"> <arguments> <argument name="type" xsi:type="string">upsell</argument> + <argument name="view_model" xsi:type="object">Magento\Catalog\ViewModel\Product\Listing\PreparePostData</argument> </arguments> <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="upsell.product.addto" as="addto"> <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare" diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml index 5a31f3d125c81..24cae93ca61c0 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/image.phtml @@ -4,11 +4,15 @@ * See COPYING.txt for license details. */ ?> -<?php /** @var $block \Magento\Catalog\Block\Product\Image */ ?> +<?php +/** @var $block \Magento\Catalog\Block\Product\Image */ +/** @var $escaper \Magento\Framework\Escaper */ +?> -<img class="photo image <?= $block->escapeHtmlAttr($block->getClass()) ?>" - <?= $block->escapeHtml($block->getCustomAttributes()) ?> - src="<?= $block->escapeUrl($block->getImageUrl()) ?>" - width="<?= $block->escapeHtmlAttr($block->getWidth()) ?>" - height="<?= $block->escapeHtmlAttr($block->getHeight()) ?>" - alt="<?= /* @noEscape */ $block->stripTags($block->getLabel(), null, true) ?>" /> +<img class="photo image <?= $escaper->escapeHtmlAttr($block->getClass()) ?>" + <?= $escaper->escapeHtml($block->getCustomAttributes()) ?> + src="<?= $escaper->escapeUrl($block->getImageUrl()) ?>" + loading="lazy" + width="<?= $escaper->escapeHtmlAttr($block->getWidth()) ?>" + height="<?= $escaper->escapeHtmlAttr($block->getHeight()) ?>" + alt="<?= $escaper->escapeHtmlAttr($block->getLabel()) ?>" /> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml index 33f7620f1a1f5..e8ddabce504ea 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/image_with_borders.phtml @@ -4,16 +4,20 @@ * See COPYING.txt for license details. */ ?> -<?php /** @var $block \Magento\Catalog\Block\Product\Image */ ?> +<?php +/** @var $block \Magento\Catalog\Block\Product\Image */ +/** @var $escaper \Magento\Framework\Escaper */ +?> <span class="product-image-container" - style="width:<?= $block->escapeHtmlAttr($block->getWidth()) ?>px;"> + style="width:<?= $escaper->escapeHtmlAttr($block->getWidth()) ?>px;"> <span class="product-image-wrapper" style="padding-bottom: <?= ($block->getRatio() * 100) ?>%;"> - <img class="<?= $block->escapeHtmlAttr($block->getClass()) ?>" - <?= $block->escapeHtmlAttr($block->getCustomAttributes()) ?> - src="<?= $block->escapeUrl($block->getImageUrl()) ?>" - max-width="<?= $block->escapeHtmlAttr($block->getWidth()) ?>" - max-height="<?= $block->escapeHtmlAttr($block->getHeight()) ?>" - alt="<?= /* @noEscape */ $block->stripTags($block->getLabel(), null, true) ?>"/></span> + <img class="<?= $escaper->escapeHtmlAttr($block->getClass()) ?>" + <?= $escaper->escapeHtmlAttr($block->getCustomAttributes()) ?> + src="<?= $escaper->escapeUrl($block->getImageUrl()) ?>" + loading="lazy" + width="<?= $escaper->escapeHtmlAttr($block->getWidth()) ?>" + height="<?= $escaper->escapeHtmlAttr($block->getHeight()) ?>" + alt="<?= $escaper->escapeHtmlAttr($block->getLabel()) ?>"/></span> </span> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml index fc4d85044a8d6..89dcef49d2bac 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml @@ -4,6 +4,9 @@ * See COPYING.txt for license details. */ +use Magento\Catalog\ViewModel\Product\Listing\PreparePostData; +use Magento\Framework\App\ActionInterface; + // phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis // phpcs:disable Generic.WhiteSpace.ScopeIndent.Incorrect // phpcs:disable Generic.Files.LineLength @@ -156,6 +159,7 @@ switch ($type = $block->getType()) { default: $exist = null; } +$_item = null; ?> <?php if ($exist):?> @@ -170,13 +174,15 @@ switch ($type = $block->getType()) { <div class="block <?= $block->escapeHtmlAttr($class) ?>"> <?php endif; ?> <div class="block-title title"> - <strong id="block-<?= $block->escapeHtmlAttr($class) ?>-heading" role="heading" aria-level="2"><?= $block->escapeHtml($title) ?></strong> + <strong id="block-<?= $block->escapeHtmlAttr($class) ?>-heading" role="heading" + aria-level="2"><?= $block->escapeHtml($title) ?></strong> </div> <div class="block-content content" aria-labelledby="block-<?= $block->escapeHtmlAttr($class) ?>-heading"> <?php if ($type == 'related' && $canItemsAddToCart):?> <div class="block-actions"> <?= $block->escapeHtml(__('Check items to add to the cart or')) ?> - <button type="button" class="action select" data-role="select-all"><span><?= $block->escapeHtml(__('select all')) ?></span></button> + <button type="button" class="action select" + data-role="select-all"><span><?= $block->escapeHtml(__('select all')) ?></span></button> </div> <?php endif; ?> <div class="products wrapper grid products-grid products-<?= $block->escapeHtmlAttr($type) ?>"> @@ -195,11 +201,15 @@ switch ($type = $block->getType()) { <?php endif; ?> <div class="product-item-info <?= /* @noEscape */ $available ?>"> <?= /* @noEscape */ '<!-- ' . $image . '-->' ?> - <a href="<?= $block->escapeUrl($block->getProductUrl($_item)) ?>" class="product photo product-item-photo"> + <a href="<?= $block->escapeUrl($block->getProductUrl($_item)) ?>" + class="product photo product-item-photo"> <?= $block->getImage($_item, $image)->toHtml() ?> </a> <div class="product details product-item-details"> - <strong class="product name product-item-name"><a class="product-item-link" title="<?= $block->escapeHtml($_item->getName()) ?>" href="<?= $block->escapeUrl($block->getProductUrl($_item)) ?>"> + <strong class="product name product-item-name"><a + class="product-item-link" + title="<?= $block->escapeHtmlAttr($_item->getName()) ?>" + href="<?= $block->escapeUrl($block->getProductUrl($_item)) ?>"> <?= $block->escapeHtml($_item->getName()) ?></a> </strong> @@ -209,52 +219,88 @@ switch ($type = $block->getType()) { <?= $block->getReviewsSummaryHtml($_item, $templateType) ?> <?php endif; ?> - <?php if ($canItemsAddToCart && !$_item->isComposite() && $_item->isSaleable() && $type == 'related'):?> + <?php if ($canItemsAddToCart && !$_item->isComposite() && $_item->isSaleable() + && $type == 'related'):?> <?php if (!$_item->getRequiredOptions()):?> - <div class="field choice related"> - <input type="checkbox" class="checkbox related" id="related-checkbox<?= $block->escapeHtmlAttr($_item->getId()) ?>" name="related_products[]" value="<?= $block->escapeHtmlAttr($_item->getId()) ?>" /> - <label class="label" for="related-checkbox<?= $block->escapeHtmlAttr($_item->getId()) ?>"><span><?= $block->escapeHtml(__('Add to Cart')) ?></span></label> + <div class="field choice related"><input + type="checkbox" + class="checkbox related" + id="related-checkbox<?= $block->escapeHtmlAttr($_item->getId()) ?>" + name="related_products[]" + value="<?= $block->escapeHtmlAttr($_item->getId()) ?>" /> + <label + class="label" + for="related-checkbox<?= $block->escapeHtmlAttr( + $_item->getId() + ) ?>"><span><?= $block->escapeHtml(__('Add to Cart')) ?></span> + </label> </div> <?php endif; ?> <?php endif; ?> <?php if ($showAddTo || $showCart):?> + <?php // phpcs:disable ?> <div class="product actions product-item-actions"> <?php if ($showCart):?> - <div class="actions-primary"> - <?php if ($_item->isSaleable()):?> - <?php if ($_item->getTypeInstance()->hasRequiredOptions($_item)):?> - <button class="action tocart primary" data-mage-init='{"redirectUrl": {"url": "<?= $block->escapeUrl($block->getAddToCartUrl($_item)) ?>"}}' type="button" title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>"> - <span><?= $block->escapeHtml(__('Add to Cart')) ?></span> - </button> - <?php else:?> - <?php $postDataHelper = $this->helper(Magento\Framework\Data\Helper\PostHelper::class); - $postData = $postDataHelper->getPostData($block->escapeUrl($block->getAddToCartUrl($_item)), ['product' => $_item->getEntityId()]) - ?> - <button class="action tocart primary" - data-post='<?= /* @noEscape */ $postData ?>' - type="button" title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>"> + <?php if ($_item->isSaleable()):?> + <div class="actions-primary"> + <?php if (!$_item->getTypeInstance()->isPossibleBuyFromList($_item)):?> + <button + class="action tocart primary" + data-mage-init='{"redirectUrl": {"url": "<?= $block->escapeUrl($block->getAddToCartUrl($_item)) ?>"}}' type="button" title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>"> + <span><?= $block->escapeHtml(__('Add to Cart')) ?></span> + </button> + <?php else :?> + <?php + /** @var $viewModel PreparePostData */ + $viewModel = $block->getViewModel(); + $postArray = $viewModel->getPostData( + $block->escapeUrl($block->getAddToCartUrl($_item)), + ['product' => $_item->getEntityId()] + ); + $value = $postArray['data'][ActionInterface::PARAM_NAME_URL_ENCODED]; + ?> + <form data-role="tocart-form" + data-product-sku="<?= $block->escapeHtmlAttr($_item->getSku()) ?>" + action="<?= $block->escapeUrl($block->getAddToCartUrl($_item)) ?>" + method="post"> + <input type="hidden" name="product" + value="<?= /* @noEscape */ (int)$_item->getEntityId() ?>"> + <input type="hidden" + name="<?= /* @noEscape */ ActionInterface::PARAM_NAME_URL_ENCODED?>" + value="<?= /* @noEscape */ $value ?>"> + <?= $block->getBlockHtml('formkey') ?> + <button type="submit" + title="<?= $block->escapeHtmlAttr(__('Add to Cart')) ?>" + class="action tocart primary"> <span><?= $block->escapeHtml(__('Add to Cart')) ?></span> </button> - <?php endif; ?> + </form> + <?php endif; ?> + <?php else:?> + <?php if ($_item->getIsSalable()):?> + <div class="stock available"> + <span><?= $block->escapeHtml(__('In stock')) ?></span> + </div> <?php else:?> - <?php if ($_item->getIsSalable()):?> - <div class="stock available"><span><?= $block->escapeHtml(__('In stock')) ?></span></div> - <?php else:?> - <div class="stock unavailable"><span><?= $block->escapeHtml(__('Out of stock')) ?></span></div> - <?php endif; ?> + <div class="stock unavailable"> + <span><?= $block->escapeHtml(__('Out of stock')) ?></span> + </div> <?php endif; ?> + <?php endif; ?> </div> <?php endif; ?> <?php if ($showAddTo):?> - <div class="secondary-addto-links actions-secondary" data-role="add-to-links"> + <div class="secondary-addto-links actions-secondary" + data-role="add-to-links"> <?php if ($addToBlock = $block->getChildBlock('addto')):?> <?= $addToBlock->setProduct($_item)->getChildHtml() ?> <?php endif; ?> </div> <?php endif; ?> </div> + <?php // phpcs:enable ?> <?php endif; ?> </div> </div> @@ -264,4 +310,15 @@ switch ($type = $block->getType()) { </div> </div> </div> + <?php if (!$block->isRedirectToCartEnabled() && $_item):?> + <script type="text/x-magento-init"> + { + "[data-role=tocart-form], .form.map.checkout": { + "catalogAddToCart": { + "product_sku": "<?= $block->escapeJs($_item->getSku()) ?>" + } + } + } + </script> + <?php endif;?> <?php endif;?> diff --git a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php index 53d3b624285e9..1057d21283ea8 100644 --- a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php +++ b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php @@ -123,7 +123,7 @@ private function addVisibilityFilter(SearchCriteriaInterface $searchCriteria, bo { if ($isFilter && $isSearch) { // Index already contains products filtered by visibility: catalog, search, both - return ; + return; } $visibilityIds = $isSearch ? $this->visibility->getVisibleInSearchIds() diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index ae5f0f5d79e2a..d1bce7aaaf951 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -307,6 +307,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity // Can't add new translated strings in patch release 'invalidLayoutUpdate' => 'Invalid format.', 'insufficientPermissions' => 'Invalid format.', + ValidatorInterface::ERROR_SKU_MARGINAL_WHITESPACES => 'SKU contains marginal whitespaces' ]; //@codingStandardsIgnoreEnd diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/RowValidatorInterface.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/RowValidatorInterface.php index f41596ad185a6..f13b603003898 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/RowValidatorInterface.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/RowValidatorInterface.php @@ -87,6 +87,8 @@ interface RowValidatorInterface extends \Magento\Framework\Validator\ValidatorIn const ERROR_DUPLICATE_MULTISELECT_VALUES = 'duplicatedMultiselectValues'; + const ERROR_SKU_MARGINAL_WHITESPACES = 'skuMarginalWhitespaces'; + /** * Value that means all entities (e.g. websites, groups etc.) */ diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php index 4b7416f6ad9a6..b2eca68db4d1c 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php @@ -10,7 +10,7 @@ use Magento\Catalog\Model\Product\Attribute\Backend\Sku; /** - * Class Validator + * Product import model validator * * @api * @since 100.0.2 @@ -72,8 +72,12 @@ protected function textValidation($attrCode, $type) $val = $this->string->cleanString($this->_rowData[$attrCode]); if ($type == 'text') { $valid = $this->string->strlen($val) < Product::DB_MAX_TEXT_LENGTH; - } else if ($attrCode == Product::COL_SKU) { + } elseif ($attrCode == Product::COL_SKU) { $valid = $this->string->strlen($val) <= SKU::SKU_MAX_LENGTH; + if ($this->string->strlen($val) !== $this->string->strlen(trim($val))) { + $this->_addMessages([RowValidatorInterface::ERROR_SKU_MARGINAL_WHITESPACES]); + return false; + } } else { $valid = $this->string->strlen($val) < Product::DB_MAX_VARCHAR_LENGTH; } @@ -359,5 +363,7 @@ public function init($context) foreach ($this->validators as $validator) { $validator->init($context); } + + return $this; } } diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml index 369805a94dd84..5415f75879ae8 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml @@ -106,7 +106,10 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportGroupedProductWithSpecialPriceTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportGroupedProductWithSpecialPriceTest.xml index d9b93196db060..adc511542074b 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportGroupedProductWithSpecialPriceTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportGroupedProductWithSpecialPriceTest.xml @@ -70,7 +70,7 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml index 642bbfc0453c5..9ff9f54d36939 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml @@ -152,7 +152,10 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridColumnsInitial"/> <!-- Admin logout--> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to System > Export --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml index 397c1ee57e7f5..03314206fa67f 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml @@ -94,7 +94,10 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml index e00346654ecf4..b199f4546b909 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml @@ -110,7 +110,10 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml index 04be8f3ae823e..578a9586a36c5 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml @@ -95,7 +95,10 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml index 8553fb8a2cf7e..cefd412025158 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductWithCustomAttributeTest.xml @@ -47,7 +47,7 @@ <argument name="rowIndex" value="0"/> </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to export page --> diff --git a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/QuoteItemQtyList.php b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/QuoteItemQtyList.php index c0b60c9935d71..600bf9897a036 100644 --- a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/QuoteItemQtyList.php +++ b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator/QuoteItemQtyList.php @@ -5,6 +5,9 @@ */ namespace Magento\CatalogInventory\Model\Quote\Item\QuantityValidator; +/** + * Class QuoteItemQtyList collects qty of quote items + */ class QuoteItemQtyList { /** @@ -17,6 +20,7 @@ class QuoteItemQtyList /** * Get product qty includes information from all quote items + * * Need be used only in singleton mode * * @param int $productId @@ -29,9 +33,7 @@ class QuoteItemQtyList public function getQty($productId, $quoteItemId, $quoteId, $itemQty) { $qty = $itemQty; - if (isset( - $this->_checkedQuoteItems[$quoteId][$productId]['qty'] - ) && !in_array( + if (isset($this->_checkedQuoteItems[$quoteId][$productId]['qty']) && !in_array( $quoteItemId, $this->_checkedQuoteItems[$quoteId][$productId]['items'] ) @@ -39,8 +41,10 @@ public function getQty($productId, $quoteItemId, $quoteId, $itemQty) $qty += $this->_checkedQuoteItems[$quoteId][$productId]['qty']; } - $this->_checkedQuoteItems[$quoteId][$productId]['qty'] = $qty; - $this->_checkedQuoteItems[$quoteId][$productId]['items'][] = $quoteItemId; + if ($quoteItemId !== null) { + $this->_checkedQuoteItems[$quoteId][$productId]['qty'] = $qty; + $this->_checkedQuoteItems[$quoteId][$productId]['items'][] = $quoteItemId; + } return $qty; } diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AdminCreateProductWithZeroMaximumQtyAllowedInShoppingCartTest.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AdminCreateProductWithZeroMaximumQtyAllowedInShoppingCartTest.xml index 74b24209682ff..43f16c0fa475e 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AdminCreateProductWithZeroMaximumQtyAllowedInShoppingCartTest.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AdminCreateProductWithZeroMaximumQtyAllowedInShoppingCartTest.xml @@ -28,7 +28,7 @@ <after> <createData entity="DefaultValueForMaxSaleQty" stepKey="setDefaultValueForMaxSaleQty"/> <deleteData createDataKey="createdProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Inventory configuration page --> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml index 8458fcf3b94e0..d0e3819ccc3cc 100644 --- a/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml @@ -80,13 +80,16 @@ </before> <after> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="simplecategory" stepKey="deleteSimpleCategory"/> - <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> - <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> - <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - </after> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="simplecategory" stepKey="deleteSimpleCategory"/> + <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + </after> <!-- Login as a customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signUpNewUser"> @@ -132,7 +135,7 @@ <waitForLoadingMaskToDisappear stepKey="waitForShipLoadingMask"/> <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="submitShipment"/> <waitForPageLoad stepKey="waitShipmentCreated"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI stepKey="runCron" command="cron:run --group='index'"/> <!-- Wait till cron job runs for schedule updates --> diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php new file mode 100644 index 0000000000000..59a391581fb06 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogInventory\Test\Unit\Model\Quote\Item\QuantityValidator; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\TestCase; +use Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\QuoteItemQtyList; + +/** + * Class QuoteItemQtyListTest + * + * Test for QuoteItemQtyList class + */ +class QuoteItemQtyListTest extends TestCase +{ + /** + * @var QuoteItemQtyList + */ + private $quoteItemQtyList; + + /** + * @var int + */ + private $itemQtyTestValue; + + /** + * Sets up the fixture, for example, open a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + $this->quoteItemQtyList = $objectManagerHelper->getObject(QuoteItemQtyList::class); + } + + /** + * This tests the scenario when item has not quote_item_id and after save gets a value. + * + * @return void + */ + public function testSingleQuoteItemQty() + { + $this->itemQtyTestValue = 1; + $qty = $this->quoteItemQtyList->getQty(125, null, 11232, 1); + $this->assertEquals($this->itemQtyTestValue, $qty); + + $qty = $this->quoteItemQtyList->getQty(125, 1, 11232, 1); + $this->assertEquals($this->itemQtyTestValue, $qty); + } + + /** + * This tests the scenario when item has been added twice to the cart. + * + * @return void + */ + public function testMultipleQuoteItemQty() + { + $this->itemQtyTestValue = 1; + $qty = $this->quoteItemQtyList->getQty(127, 1, 112, 1); + $this->assertEquals($this->itemQtyTestValue, $qty); + + $this->itemQtyTestValue = 2; + $qty = $this->quoteItemQtyList->getQty(127, 2, 112, 1); + $this->assertEquals($this->itemQtyTestValue, $qty); + } +} diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/OpenCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/OpenCatalogPriceRuleActionGroup.xml index c810d9579df92..68ce445d991b3 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/OpenCatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/OpenCatalogPriceRuleActionGroup.xml @@ -13,6 +13,7 @@ <argument name="ruleName" type="string" defaultValue="CustomCatalogRule.name"/> </arguments> <amOnPage url="{{AdminCatalogPriceRuleGridPage.url}}" stepKey="goToAdminCatalogPriceRuleGridPage"/> + <waitForPageLoad stepKey="waitForAdminCatalogPriceRuleGridPageLoad"/> <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/> <fillField selector="{{AdminCatalogPriceRuleGridSection.filterByRuleName}}" userInput="{{ruleName}}" stepKey="filterByRuleName"/> <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearch"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml index d99ebac94fbec..bf4ec749d7264 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml @@ -84,7 +84,7 @@ </actionGroup> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <!-- Delete all created data --> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> @@ -92,6 +92,9 @@ <deleteData createDataKey="createSecondConfigChildProduct" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add special prices for products --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml index 83dff1ecdcab5..4211f0fc76508 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateInactiveCatalogPriceRuleTest.xml @@ -28,7 +28,7 @@ <argument name="catalogRuleName" value="{{InactiveCatalogRule.name}}"/> </actionGroup> <actionGroup ref="AdminDeleteCatalogRuleActionGroup" stepKey="deleteTheCatalogRule"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Inactive Catalog Price Rule --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 02d998870fb65..730e04bfea7cf 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -42,7 +42,7 @@ <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer1"/> <deleteData createDataKey="createProduct1" stepKey="deleteSimpleProduct1"/> @@ -174,7 +174,7 @@ <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory1" stepKey="deleteCategory1"/> @@ -182,6 +182,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute1" stepKey="deleteConfigProductAttribute1"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Delete the simple product and catalog price rule --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml index a6eb6eb1e5178..dfb846e90b669 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml @@ -43,7 +43,7 @@ <amOnPage url="{{AdminCatalogPriceRuleGridPage.url}}" stepKey="goToCatalogRuleGridPage"/> <waitForPageLoad stepKey="waitForCatalogRuleGridPageLoaded"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCatalogRuleGridFilters"/> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <!-- Create a catalog price rule --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml index da855b08cf390..0df73c99595a6 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml @@ -62,7 +62,7 @@ <deleteData createDataKey="createSecondCategory" stepKey="deleteSecondCategory"/> <deleteData createDataKey="createSecondProductAttribute" stepKey="deleteSecondProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminMarketingCatalogPriceRuleNavigateMenuTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminMarketingCatalogPriceRuleNavigateMenuTest.xml index 0fe35419aaf3e..2a45de28db199 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminMarketingCatalogPriceRuleNavigateMenuTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminMarketingCatalogPriceRuleNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToCatalogPriceRulePage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml index 1615985370182..feb9423151299 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml @@ -104,7 +104,10 @@ </actionGroup> <click stepKey="resetFilters" selector="{{AdminSecondaryGridSection.resetFilters}}"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add values to your attribute ( ex: red , green) --> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index 02d6d90ae5d0e..2790dfbe46fda 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -87,7 +87,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Delete products and category --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> @@ -96,6 +96,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Begin creating a new catalog price rule --> <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml index bb0a890fd0974..0149a2d0a6abb 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductAndFixedMethodTest.xml @@ -47,7 +47,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Begin creating a new catalog price rule --> <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index 4ab2d0d491548..c70a72d725489 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -58,7 +58,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Begin creating a new catalog price rule --> <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml index 166d202ec2410..9ebab2d28249a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductWithCustomOptionsTest.xml @@ -63,7 +63,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Begin creating a new catalog price rule --> <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="newCatalogPriceRuleByUIWithConditionIsCategory"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 86d3dccba7595..8130bdaae6303 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -15,71 +15,88 @@ <title value="Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie"/> <description value="Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-69455"/> + <testCaseId value="MC-27571"/> <group value="persistent"/> </annotations> <before> - <createData entity="PersistentConfigEnabled" stepKey="enablePersistent"/> - <createData entity="PersistentLogoutClearDisable" stepKey="persistentLogoutClearDisable"/> + + <createData entity="PersistentConfigSettings" stepKey="enablePersistent"/> <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="_defaultProduct" stepKey="createProduct"> + <createData entity="productWithHTMLEntityOne" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> - <field key="price">50</field> - </createData> - <createData entity="Simple_US_Customer" stepKey="createCustomer"> - <field key="group_id">1</field> </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!--Delete all Catalog Price Rule if exist--> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + - <actionGroup ref="LoginAsAdmin" stepKey="login"/> <!--Create Catalog Rule--> - <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsCategoryActionGroup" stepKey="createCatalogPriceRule"> - <argument name="catalogRule" value="_defaultCatalogRule"/> - <argument name="categoryId" value="$$createCategory.id$$"/> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingFirstPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForFirstPriceRule"> + <argument name="groups" value="'General'"/> + </actionGroup> + <actionGroup ref="AdminFillCatalogRuleConditionActionGroup" stepKey="createCatalogPriceRule"> + <argument name="conditionValue" value="$createCategory.id$"/> </actionGroup> - <actionGroup ref="SelectGeneralCustomerGroupActionGroup" stepKey="selectCustomerGroup"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules"/> - <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccess"/> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="clickSaveAndApplyRule"/> + + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> <after> - <!-- Delete the rule --> - <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToCatalogPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{_defaultCatalogRule.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> <createData entity="PersistentLogoutClearEnabled" stepKey="persistentLogoutClearEnabled"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!-- Delete the rule --> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to category and check price--> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="checkPriceSimpleProduct"/> + <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPage"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> <!--Login to storefront from customer and check price--> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="logInFromCustomer"> - <argument name="Customer" value="$$createCustomer$$"/> + <argument name="Customer" value="$createCustomer$"/> + </actionGroup> + <actionGroup ref="AssertCustomerWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomer"> + <argument name="customerFullName" value="{{Simple_Customer_Without_Address.fullname}}"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage2"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome"/> - <see selector="{{StorefrontCategoryProductSection.ProductSpecialPriceByNumber('1')}}" userInput="45.00" stepKey="checkPriceSimpleProduct2"/> - <!--Click *Sign Out* and check the price of the Simple Product--> + <!--Go to category and check special price--> + <actionGroup ref="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" stepKey="assertProductSpecialPriceInCategoryPage"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + + + <!--Click *Sign Out*--> <actionGroup ref="StorefrontSignOutActionGroup" stepKey="storefrontSignOut"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage3"/> - <see userInput="Welcome, $$createCustomer.firstname$$ $$createCustomer.lastname$$!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome2"/> - <seeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkLinkNotYoy"/> - <see selector="{{StorefrontCategoryProductSection.ProductSpecialPriceByNumber('1')}}" userInput="45.00" stepKey="checkPriceSimpleProduct3"/> + <actionGroup ref="StorefrontAssertPersistentCustomerWelcomeMessageActionGroup" stepKey="seeWelcomeForJohnDoeCustomer"> + <argument name="customerFullName" value="{{Simple_Customer_Without_Address.fullname}}"/> + </actionGroup> + + <!--Go to category and check special price--> + <actionGroup ref="AssertStorefrontProductSpecialPriceInCategoryPageActionGroup" stepKey="assertProductSpecialPriceInCategoryPageAfterLogout"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> <!--Click the *Not you?* link and check the price for Simple Product--> - <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNext"/> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onStorefrontCategoryPage4"/> - <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="homeCheckWelcome3"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="checkPriceSimpleProduct4"/> + <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNotYouLink"/> + <actionGroup ref="AssertStorefrontDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> + <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPageAfterLogout"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName($createProduct.name$)}}" stepKey="dontSeeSpecialPrice"/> </test> </tests> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 3423baf7970eb..17266b0c80d7a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -16,55 +16,51 @@ <description value="Customer should not see the catalog price rule promotion if status is inactive"/> <severity value="CRITICAL"/> <testCaseId value="MC-79"/> - <group value="CatalogRule"/> - <skip> - <issueId value="MC-30384"/> - </skip> + <group value="catalogRule"/> </annotations> + <before> - <actionGroup ref="LoginAsAdmin" stepKey="login"/> <createData entity="ApiCategory" stepKey="createCategory"/> <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup stepKey="createNewPriceRule" ref="NewCatalogPriceRuleByUIActionGroup"/> - <actionGroup stepKey="selectLoggedInCustomers" ref="SelectNotLoggedInCustomerGroupActionGroup"/> - <scrollToTopOfPage stepKey="scrollToTop"/> - <click stepKey="setInactive" selector="{{AdminCategoryBasicFieldSection.enableCategoryLabel}}"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApply"/> - <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="seeSuccess"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> - <!-- Perform reindex and flush cache --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingFirstPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForFirstPriceRule"> + <argument name="active" value="0"/> + <argument name="groups" value="'NOT LOGGED IN'"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyFirstPriceRule"/> + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> + <after> <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{_defaultCatalogRule.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> - <amOnPage url="{{AdminLogoutPage.url}}" stepKey="logout"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!-- Verify price is not discounted on category page --> - <amOnPage url="$$createCategory.name$$.html" stepKey="goToCategory"/> - <waitForPageLoad stepKey="waitForCategory"/> - <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="seePrice1"/> + <amOnPage url="{{StorefrontCategoryPage.url($createCategory.custom_attributes[url_key]$)}}" stepKey="openCategoryPageOnFrontend"/> + <waitForPageLoad stepKey="waitForCategoryPageLoaded"/> + <see selector="{{StorefrontCategoryProductSection.ProductPriceByNumber('1')}}" userInput="$$createProduct.price$$" stepKey="seeProductPriceOnCategoryPage"/> <!-- Verify price is not discounted on the product page --> - <amOnPage url="$$createProduct.sku$$.html" stepKey="goToProduct"/> - <waitForPageLoad stepKey="waitForProduct"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createProduct.price$$" stepKey="seePrice2"/> + <amOnPage url="{{StorefrontProductPage.url($createProduct.custom_attributes[url_key]$)}}" stepKey="openProductPageOnFrontend"/> + <waitForPageLoad stepKey="waitForProductPageLoaded"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$createProduct.price$" stepKey="seePriceOnProductPage"/> <!-- Verify price is not discounted in the cart --> - <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart"/> - <waitForPageLoad stepKey="waitForCart"/> - <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> - <amOnPage url="{{CheckoutCartPage.url}}" stepKey="goToCheckout"/> - <waitForPageLoad stepKey="waitForCheckout"/> - <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$$createProduct.price$$" stepKey="seePrice3"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontOpenCartPageActionGroup" stepKey="openCartPage" /> + <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalAppears"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$createProduct.price$" stepKey="seeProductPriceOnCartPage"/> </test> </tests> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml index 8b72b7616b6ff..56e0573649d29 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml @@ -171,7 +171,10 @@ <!-- Delete created price rules --> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create catalog price rule --> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml index c110daee35428..bd73501b6117e 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -175,7 +175,10 @@ </actionGroup> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule --> <actionGroup ref="NewCatalogPriceRuleByUIActionGroup" stepKey="createPriceRule"> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml index bc6c89f2f1155..1cc2a8cb57256 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml @@ -105,7 +105,10 @@ <deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule for first configurable product option --> diff --git a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml index 05f30fd6fcbde..2375d50d73e3c 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml @@ -122,7 +122,10 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create price rule for first configurable product option --> diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php index d8947ac4224a8..b1aecc6885bf0 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Attribute.php @@ -67,7 +67,8 @@ public function apply(\Magento\Framework\App\RequestInterface $request) $labels = []; foreach ((array) $attributeValue as $value) { - $labels[] = (array) $this->getOptionText($value); + $label = $this->getOptionText($value); + $labels[] = is_array($label) ? $label : [$label]; } $label = implode(',', array_unique(array_merge(...$labels))); $this->getLayer() diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontFillFormAdvancedSearchWithCustomDropDownAttributeActionGroup.xml b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontFillFormAdvancedSearchWithCustomDropDownAttributeActionGroup.xml new file mode 100644 index 0000000000000..1618465769a66 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/ActionGroup/StorefrontFillFormAdvancedSearchWithCustomDropDownAttributeActionGroup.xml @@ -0,0 +1,21 @@ +<?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="StorefrontFillFormAdvancedSearchWithCustomDropDownAttributeActionGroup" extends="StorefrontFillFormAdvancedSearchActionGroup"> + <annotations> + <description>Fills in the advanced search form and select the attribute.</description> + </annotations> + <arguments> + <argument name="attributeCode" type="string" defaultValue="{{productDropDownAttribute.attribute_code}}"/> + <argument name="optionName" type="string" defaultValue="{{productAttributeOption1.label}}"/> + </arguments> + <selectOption userInput="{{optionName}}" selector="{{StorefrontCatalogSearchAdvancedFormSection.AttributeByCode(attributeCode)}}" before="clickSubmit" stepKey="selectOption"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminCreateSearchTermEntityTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminCreateSearchTermEntityTest.xml index 86a1d4321cba0..2ab87b3ceb967 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminCreateSearchTermEntityTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminCreateSearchTermEntityTest.xml @@ -35,7 +35,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to the search terms page and create new search term --> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminDeleteSearchTermTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminDeleteSearchTermTest.xml index b449d92d8e003..a950fb6c379cb 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminDeleteSearchTermTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminDeleteSearchTermTest.xml @@ -29,7 +29,7 @@ <after> <deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/> <deleteData stepKey="deleteSimpleProduct" createDataKey="simpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Add new search term--> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminMarketingSearchTermsNavigateMenuTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminMarketingSearchTermsNavigateMenuTest.xml index bc255020d98b3..6be63541f3c27 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminMarketingSearchTermsNavigateMenuTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminMarketingSearchTermsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToMarketingSearchTermsPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminReportsSearchTermsNavigateMenuTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminReportsSearchTermsNavigateMenuTest.xml index 85cf0e3ba90ed..e1a965bd08e0b 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminReportsSearchTermsNavigateMenuTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/AdminReportsSearchTermsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportSearchTermsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/LayerNavigationOfCatalogSearchTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/LayerNavigationOfCatalogSearchTest.xml index fa9407495e6e7..c8055d85c98ea 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/LayerNavigationOfCatalogSearchTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/LayerNavigationOfCatalogSearchTest.xml @@ -38,7 +38,7 @@ <deleteData stepKey="deleteSimpleProduct1" createDataKey="simpleProduct1"/> <deleteData stepKey="deleteSimpleProduct2" createDataKey="simpleProduct2"/> <deleteData createDataKey="createPriceAttribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update value for price attribute of Product 1--> <comment userInput="Update value for price attribute of Product 1" stepKey="comment1"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml index 89269a1ad0d9e..6ae215f821a0b 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml @@ -31,7 +31,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <createData entity="SetMinQueryLengthToDefault" stepKey="setMinimumQueryLengthToDefault"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="SetMinimalQueryLengthActionGroup" stepKey="setMinQueryLength"/> <comment userInput="Go to Storefront and search for product" stepKey="searchProdUsingMinQueryLength"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index 7648b59aaefe8..dc715a5d95f2f 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -385,7 +385,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> @@ -465,7 +465,7 @@ <after> <deleteData stepKey="deleteGroupedProduct" createDataKey="createProduct"/> <deleteData stepKey="deleteSimpleProduct" createDataKey="simple1"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> @@ -517,7 +517,7 @@ <deleteData stepKey="deleteBundleProduct" createDataKey="createBundleProduct"/> <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> <deleteData stepKey="deleteCategory" createDataKey="createCategory"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> @@ -586,7 +586,7 @@ <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> <deleteData stepKey="deleteCategory" createDataKey="createCategory"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <comment userInput="$simpleProduct1.name$" stepKey="asdf"/> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontAdvancedSearchEntitySimpleProductTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontAdvancedSearchEntitySimpleProductTest.xml index 61f274cd13061..f032a97ac297c 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontAdvancedSearchEntitySimpleProductTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontAdvancedSearchEntitySimpleProductTest.xml @@ -28,7 +28,7 @@ <after> <!-- Delete data --> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logoutAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdmin"/> </after> <!-- Perform reindex and flush cache --> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml index 44a4001f7b579..5c3f55c7212ad 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -81,7 +81,7 @@ <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml index fab28dc357016..502301939f71a 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontUpdateSearchTermEntityTest.xml @@ -41,7 +41,7 @@ <comment userInput="Delete all search terms" stepKey="deleteAllSearchTermsComment"/> <actionGroup ref="AdminDeleteAllSearchTermsActionGroup" stepKey="deleteAllSearchTerms"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> </after> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName1"> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminCategoryWithRestrictedUrlKeyNotCreatedTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminCategoryWithRestrictedUrlKeyNotCreatedTest.xml index c3c7e3c3281f4..cb969ac2d329e 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminCategoryWithRestrictedUrlKeyNotCreatedTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminCategoryWithRestrictedUrlKeyNotCreatedTest.xml @@ -36,7 +36,7 @@ <actionGroup ref="AdminDeleteCategoryByNameActionGroup" stepKey="deleteGraphQlCategory"> <argument name="categoryName" value="graphql"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Check category creation with restricted url key 'admin'--> <comment userInput="Check category creation with restricted url key 'admin'" stepKey="commentCheckAdminCategoryCreation"/> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml index cc5f09faca57b..453f18003e694 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/AdminUrlForProductRewrittenCorrectlyTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Created product--> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/RewriteStoreLevelUrlKeyOfChildCategoryTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/RewriteStoreLevelUrlKeyOfChildCategoryTest.xml index c3a358bbbd292..e176fba9fd189 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/RewriteStoreLevelUrlKeyOfChildCategoryTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/RewriteStoreLevelUrlKeyOfChildCategoryTest.xml @@ -58,7 +58,7 @@ <after> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="subCategory" stepKey="deleteSubCategory"/> <deleteData createDataKey="defaultCategory" stepKey="deleteNewRootCategory"/> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml index 6674c55064169..99037a5c89af1 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml @@ -13,6 +13,7 @@ <title value="Storefront category is accessible when url suffix is set to null test"/> <description value="Check no crash occurs on Category page when catalog/seo/category_url_suffix is set to null"/> <features value="CatalogUrlRewrite"/> + <stories value="Url rewrites"/> <severity value="MAJOR"/> <group value="CatalogUrlRewrite"/> </annotations> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductProcessUrlRewriteRemovingObserverTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductProcessUrlRewriteRemovingObserverTest.php new file mode 100644 index 0000000000000..7184f1b3cd275 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/ProductProcessUrlRewriteRemovingObserverTest.php @@ -0,0 +1,148 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\CatalogUrlRewrite\Test\Unit\Observer; + +use Magento\Catalog\Model\Product; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\CatalogUrlRewrite\Observer\ProductProcessUrlRewriteRemovingObserver; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for Magento\CatalogUrlRewrite\Observer\ProductProcessUrlRewriteRemovingObserver + */ +class ProductProcessUrlRewriteRemovingObserverTest extends TestCase +{ + /* + * Stub product ID + */ + private const STUB_PRODUCT_ID = 333; + + /** + * Testable Object + * + * @var ProductProcessUrlRewriteRemovingObserver + */ + private $observer; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * @var Product|MockObject + */ + private $productMock; + + /** + * @var UrlPersistInterface|MockObject + */ + private $urlPersistMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getProduct']) + ->getMock(); + + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMock(); + + $this->urlPersistMock = $this->getMockBuilder(UrlPersistInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->observer = $this->objectManager->getObject( + ProductProcessUrlRewriteRemovingObserver::class, + [ + 'urlPersist' => $this->urlPersistMock + ] + ); + } + + /** + * Test for execute(), covers test case for removing product URLs from storage + */ + public function testRemoveProductUrlsFromStorage(): void + { + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->productMock + ->expects($this->exactly(2)) + ->method('getId') + ->willReturn(self::STUB_PRODUCT_ID); + + $this->urlPersistMock->expects($this->once()) + ->method('deleteByData') + ->with([ + UrlRewrite::ENTITY_ID => self::STUB_PRODUCT_ID, + UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, + ]); + + $this->observer->execute($this->observerMock); + } + + /** + * Test for execute(), covers test case for removing product URLs when the product doesn't have an ID + */ + public function testRemoveProductUrlsWithEmptyProductId() + { + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->productMock + ->expects($this->once()) + ->method('getId') + ->willReturn(null); + + $this->urlPersistMock->expects($this->never())->method('deleteByData'); + + $this->observer->execute($this->observerMock); + } +} diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php index eca994de0892f..f9340a495de65 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\ProductCategoryList; +use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Store\Model\Store; /** @@ -122,46 +123,34 @@ protected function _addSpecialAttributes(array &$attributes) /** * Add condition to collection * - * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection + * @param Collection $collection * @return $this */ public function addToCollection($collection) { $attribute = $this->getAttributeObject(); + $attributeCode = $attribute->getAttributeCode(); + if ($attributeCode !== 'price' || !$collection->getLimitationFilters()->isUsingPriceIndex()) { + if ($collection->isEnabledFlat()) { + if ($attribute->isEnabledInFlat()) { + $alias = array_keys($collection->getSelect()->getPart('from'))[0]; + $this->joinedAttributes[$attributeCode] = $alias . '.' . $attributeCode; + } else { + $alias = 'at_' . $attributeCode; + if (!in_array($alias, array_keys($collection->getSelect()->getPart('from')))) { + $collection->joinAttribute($attributeCode, "catalog_product/$attributeCode", 'entity_id'); + } - if ($collection->isEnabledFlat()) { - if ($attribute->isEnabledInFlat()) { - $alias = array_keys($collection->getSelect()->getPart('from'))[0]; - $this->joinedAttributes[$attribute->getAttributeCode()] = $alias . '.' . $attribute->getAttributeCode(); - } else { - $alias = 'at_' . $attribute->getAttributeCode(); - if (!in_array($alias, array_keys($collection->getSelect()->getPart('from')))) { - $collection->joinAttribute( - $attribute->getAttributeCode(), - 'catalog_product/'.$attribute->getAttributeCode(), - 'entity_id' - ); + $this->joinedAttributes[$attributeCode] = $alias . '.value'; } - - $this->joinedAttributes[$attribute->getAttributeCode()] = $alias . '.value'; + } elseif ($attributeCode !== 'category_ids' && !$attribute->isStatic()) { + $this->addAttributeToCollection($attribute, $collection); + $attributes = $this->getRule()->getCollectedAttributes(); + $attributes[$attributeCode] = true; + $this->getRule()->setCollectedAttributes($attributes); } - return $this; } - if ('category_ids' == $attribute->getAttributeCode() || $attribute->isStatic()) { - return $this; - } - - if ($attribute->getBackend() && $attribute->isScopeGlobal()) { - $this->addGlobalAttribute($attribute, $collection); - } else { - $this->addNotGlobalAttribute($attribute, $collection); - } - - $attributes = $this->getRule()->getCollectedAttributes(); - $attributes[$attribute->getAttributeCode()] = true; - $this->getRule()->setCollectedAttributes($attributes); - return $this; } @@ -169,12 +158,12 @@ public function addToCollection($collection) * Adds Attributes that belong to Global Scope * * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute - * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection + * @param Collection $collection * @return $this */ protected function addGlobalAttribute( \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute, - \Magento\Catalog\Model\ResourceModel\Product\Collection $collection + Collection $collection ) { switch ($attribute->getBackendType()) { case 'decimal': @@ -207,12 +196,12 @@ protected function addGlobalAttribute( * Adds Attributes that don't belong to Global Scope * * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute - * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection + * @param Collection $collection * @return $this */ protected function addNotGlobalAttribute( \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute, - \Magento\Catalog\Model\ResourceModel\Product\Collection $collection + Collection $collection ) { $storeId = $this->storeManager->getStore()->getId(); $values = $collection->getAllAttributeValues($attribute); @@ -255,6 +244,8 @@ public function getMappedSqlField() $result = parent::getMappedSqlField(); } elseif (isset($this->joinedAttributes[$this->getAttribute()])) { $result = $this->joinedAttributes[$this->getAttribute()]; + } elseif ($this->getAttribute() === 'price') { + $result = 'price_index.min_price'; } elseif ($this->getAttributeObject()->isStatic()) { $result = $this->getAttributeObject()->getAttributeCode(); } elseif ($this->getValueParsed()) { @@ -267,11 +258,27 @@ public function getMappedSqlField() /** * @inheritdoc * - * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection + * @param Collection $productCollection * @return $this */ public function collectValidatedAttributes($productCollection) { return $this->addToCollection($productCollection); } + + /** + * Add attribute to collection based on scope + * + * @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute + * @param Collection $collection + * @return void + */ + private function addAttributeToCollection($attribute, $collection): void + { + if ($attribute->getBackend() && $attribute->isScopeGlobal()) { + $this->addGlobalAttribute($attribute, $collection); + } else { + $this->addNotGlobalAttribute($attribute, $collection); + } + } } diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml new file mode 100644 index 0000000000000..ecc5780da0e02 --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml @@ -0,0 +1,33 @@ +<?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="AdminFillCatalogProductsListWidgetCategoryActionGroup"> + <annotations> + <description>Fill catalog products list widget category.</description> + </annotations> + + <arguments> + <argument name="categoryName" type="string" defaultValue="{{_defaultCategory.name}}"/> + </arguments> + + <waitForElementVisible selector="{{WidgetSection.AddParam}}" stepKey="waitForAddParamElement"/> + <click selector="{{WidgetSection.AddParam}}" stepKey="clickOnAddParamElement"/> + <waitForElementVisible selector="{{WidgetSection.ConditionsDropdown}}" stepKey="waitForConditionsDropdownVisible"/> + <selectOption selector="{{WidgetSection.ConditionsDropdown}}" userInput="Category" stepKey="selectCategoryAsCondition"/> + <waitForElementVisible selector="{{WidgetSection.RuleParam}}" stepKey="waitForRuleParamElementVisible"/> + <click selector="{{WidgetSection.RuleParam}}" stepKey="clickToAddRuleParam"/> + <click selector="{{WidgetSection.Chooser}}" stepKey="clickToSelectFromList"/> + <waitForPageLoad stepKey="waitForPageLoadAfterSelectingRuleParam"/> + <waitForElementVisible selector="{{WidgetSection.PreCreateCategory(categoryName)}}" stepKey="waitForCategoryElementVisible"/> + <click selector="{{WidgetSection.PreCreateCategory(categoryName)}}" stepKey="selectCategoryFromArguments"/> + <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="clickApplyButton"/> + <waitForElementNotVisible selector="{{InsertWidgetSection.categoryTreeWrapper}}" stepKey="waitForCategoryTreeIsNotVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml index 855d325c9850c..66aa4252f4b5f 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Section/CatalogWidgetSection.xml @@ -22,5 +22,6 @@ <element name="conditionOperator" type="button" selector="#conditions__1--{{arg3}}__operator" parameterized="true"/> <element name="checkElementStorefrontByPrice" type="button" selector="//*[@class='product-items widget-product-grid']//*[contains(text(),'${{arg4}}.00')]" parameterized="true"/> <element name="checkElementStorefrontByName" type="button" selector="//*[@class='product-items widget-product-grid']//*[@class='product-item'][{{productPosition}}]//a[contains(text(), '{{productName}}')]" parameterized="true"/> + <element name="categoryTreeWrapper" type="text" selector=".rule-chooser .tree.x-tree"/> </section> </sections> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOperatorsTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOperatorsTest.xml index 13ffedb1f707b..8d4e97420dd0b 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOperatorsTest.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOperatorsTest.xml @@ -151,7 +151,7 @@ <deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/> <deleteData createDataKey="createSecondProduct" stepKey="deleteSecondProduct"/> <deleteData createDataKey="createThirdProduct" stepKey="deleteThirdProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOrderTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOrderTest.xml index f0af04478bc28..ea6a3a73522e7 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOrderTest.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListWidgetOrderTest.xml @@ -82,7 +82,7 @@ <deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/> <deleteData createDataKey="createSecondProduct" stepKey="deleteSecondProduct"/> <deleteData createDataKey="createThirdProduct" stepKey="deleteThirdProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml new file mode 100644 index 0000000000000..74e1110c95636 --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml @@ -0,0 +1,93 @@ +<?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="StorefrontProductGridUIUpdatesOnDesktopTest"> + <annotations> + <features value="Catalog"/> + <stories value="New products list widget"/> + <title value="Storefront product grid UI updates on Desktop"/> + <description value="Storefront product grid UI updates on Desktop"/> + <severity value="MAJOR"/> + <testCaseId value="MC-27569"/> + <group value="catalog"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <!-- 1. Create multiple products and assign to a category. --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProduct" stepKey="createFirstSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createSecondSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createThirdSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiSimpleProduct" stepKey="createFourthSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- 2. Create new CMS page and add "Catalog Product List" widget type via content >insert widget option --> + <createData entity="_emptyCmsPage" stepKey="createCmsPage"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCmsPage"> + <argument name="CMSPage" value="$createCmsPage$"/> + </actionGroup> + <actionGroup ref="AdminInsertWidgetToCmsPageContentActionGroup" stepKey="insertWidgetToCmsPageContentActionGroup"> + <argument name="widgetType" value="Catalog Products List"/> + </actionGroup> + <actionGroup ref="AdminFillCatalogProductsListWidgetCategoryActionGroup" stepKey="fillCatalogProductsListWidgetOptions"> + <argument name="categoryName" value="$createCategory.name$"/> + </actionGroup> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetButton"/> + <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveButton"/> + </before> + <after> + <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> + <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> + <deleteData createDataKey="createThirdSimpleProduct" stepKey="deleteThirdSimpleProduct"/> + <deleteData createDataKey="createFourthSimpleProduct" stepKey="deleteFourthSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createCmsPage" stepKey="deleteCmsPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="navigateAndOpenCreatedCmsPage"> + <argument name="identifier" value="$createCmsPage.identifier$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup" stepKey="assertProductControlsAreNotVisibleWithoutHoverOnCmsPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productLinkByHref($createFirstSimpleProduct.custom_attributes[url_key]$)}}" stepKey="assertProductName"/> + <seeElement selector="{{StorefrontCategoryMainSection.productPriceByName($createFirstSimpleProduct.name$)}}" stepKey="assertProductPrice"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName($createFirstSimpleProduct.name$)}}" stepKey="hoverProduct"/> + <actionGroup ref="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup" stepKey="assertProductControlsAreVisibleOnHoverOnCmsPage"/> + <actionGroup ref="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup" stepKey="assertAddToWishListIconIsClickable"/> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="navigateAndOpenCreatedCmsPageToVerifyAddToCompareIconIsClickable"> + <argument name="identifier" value="$createCmsPage.identifier$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="assertAddToCompareIconIsClickable"> + <argument name="productVar" value="$createFirstSimpleProduct$"/> + </actionGroup> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateCategoryCreatedInPreconditions"> + <argument name="category" value="$createCategory$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup" stepKey="assertProductControlsAreNotVisibleWithoutHoverOnCategoryPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productLinkByHref($createFirstSimpleProduct.custom_attributes[url_key]$)}}" stepKey="assertProductNameOnCategoryPage"/> + <seeElement selector="{{StorefrontCategoryMainSection.productPriceByName($createFirstSimpleProduct.name$)}}" stepKey="assertProductPriceOnCategoryPage"/> + <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName($createFirstSimpleProduct.name$)}}" stepKey="hoverProductOnCategoryPage"/> + <actionGroup ref="AssertStorefrontProductControlsAreVisibleOnHoverActionGroup" stepKey="assertProductControlsAreVisibleOnHoverOnCategoryPage"/> + <actionGroup ref="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup" stepKey="assertAddToWishListIconIsClickableOnCategoryPage"/> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateCategoryCreatedInPreconditionsToVerifyAddToCompareIconIsClickable"> + <argument name="category" value="$createCategory$"/> + </actionGroup> + <actionGroup ref="StorefrontAddCategoryProductToCompareActionGroup" stepKey="assertAddToCompareIconIsClickableOnCategoryPage"> + <argument name="productVar" value="$createFirstSimpleProduct$"/> + </actionGroup> + <actionGroup ref="StorefrontClearCompareActionGroup" stepKey="clearAllCompareProducts"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 5dedf2c7e7eba..1dd1131cde1f1 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -289,6 +289,7 @@ protected function getMultilineFieldConfig($attributeCode, array $attributeConfi 'dataScope' => $lineIndex, 'provider' => $providerName, 'validation' => $isFirstLine + //phpcs:ignore Magento2.Performance.ForeachArrayMerge ? array_merge( ['required-entry' => (bool)$attributeConfig['required']], $attributeConfig['validation'] @@ -381,14 +382,14 @@ protected function getCustomer(): ?CustomerInterface /** * Retrieve field options from attribute configuration * - * @param string $attributeCode + * @param mixed $attributeCode * @param array $attributeConfig * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function getFieldOptions($attributeCode, array $attributeConfig) { - return isset($attributeConfig['options']) ? $attributeConfig['options'] : []; + return $attributeConfig['options'] ?? []; } /** diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 557f143352446..00cc06ea0ff47 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -3,24 +3,30 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Checkout\Block\Checkout; use Magento\Checkout\Helper\Data; -use Magento\Framework\App\ObjectManager; +use Magento\Customer\Model\AttributeMetadataDataProvider; +use Magento\Customer\Model\Options; +use Magento\Eav\Api\Data\AttributeInterface; +use Magento\Shipping\Model\Config; use Magento\Store\Model\StoreManagerInterface; +use Magento\Ui\Component\Form\AttributeMapper; /** - * Class LayoutProcessor + * Checkout Layout Processor */ -class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface +class LayoutProcessor implements LayoutProcessorInterface { /** - * @var \Magento\Customer\Model\AttributeMetadataDataProvider + * @var AttributeMetadataDataProvider */ private $attributeMetadataDataProvider; /** - * @var \Magento\Ui\Component\Form\AttributeMapper + * @var AttributeMapper */ protected $attributeMapper; @@ -30,7 +36,7 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso protected $merger; /** - * @var \Magento\Customer\Model\Options + * @var Options */ private $options; @@ -45,39 +51,35 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso private $storeManager; /** - * @var \Magento\Shipping\Model\Config + * @var Config */ private $shippingConfig; /** - * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider - * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper + * @param AttributeMetadataDataProvider $attributeMetadataDataProvider + * @param AttributeMapper $attributeMapper * @param AttributeMerger $merger - * @param \Magento\Customer\Model\Options|null $options - * @param Data|null $checkoutDataHelper - * @param \Magento\Shipping\Model\Config|null $shippingConfig - * @param StoreManagerInterface|null $storeManager + * @param Options $options + * @param Data $checkoutDataHelper + * @param Config $shippingConfig + * @param StoreManagerInterface $storeManager */ public function __construct( - \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider, - \Magento\Ui\Component\Form\AttributeMapper $attributeMapper, + AttributeMetadataDataProvider $attributeMetadataDataProvider, + AttributeMapper $attributeMapper, AttributeMerger $merger, - \Magento\Customer\Model\Options $options = null, - Data $checkoutDataHelper = null, - \Magento\Shipping\Model\Config $shippingConfig = null, - StoreManagerInterface $storeManager = null + Options $options, + Data $checkoutDataHelper, + Config $shippingConfig, + StoreManagerInterface $storeManager ) { $this->attributeMetadataDataProvider = $attributeMetadataDataProvider; $this->attributeMapper = $attributeMapper; $this->merger = $merger; - $this->options = $options ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Customer\Model\Options::class); - $this->checkoutDataHelper = $checkoutDataHelper ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(Data::class); - $this->shippingConfig = $shippingConfig ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Shipping\Model\Config::class); - $this->storeManager = $storeManager ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(StoreManagerInterface::class); + $this->options = $options; + $this->checkoutDataHelper = $checkoutDataHelper; + $this->shippingConfig = $shippingConfig; + $this->storeManager = $storeManager; } /** @@ -87,7 +89,7 @@ public function __construct( */ private function getAddressAttributes() { - /** @var \Magento\Eav\Api\Data\AttributeInterface[] $attributes */ + /** @var AttributeInterface[] $attributes */ $attributes = $this->attributeMetadataDataProvider->loadAttributesCollection( 'customer_address', 'customer_register_address' @@ -157,8 +159,10 @@ public function process($jsLayout) $elements = $this->getAddressAttributes(); $elements = $this->convertElementsToSelect($elements, $attributesToConvert); // The following code is a workaround for custom address attributes - if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] - ['payment']['children'])) { + if (isset( + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment'] + ['children'] + )) { $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] ['payment']['children'] = $this->processPaymentChildrenComponents( $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] @@ -166,8 +170,11 @@ public function process($jsLayout) $elements ); } - if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] - ['step-config']['children']['shipping-rates-validation']['children'])) { + + if (isset( + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + )) { $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] ['step-config']['children']['shipping-rates-validation']['children'] = $this->processShippingChildrenComponents( @@ -176,8 +183,10 @@ public function process($jsLayout) ); } - if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] - ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'])) { + if (isset( + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['shippingAddress']['children']['shipping-address-fieldset']['children'] + )) { $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']; $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] @@ -188,6 +197,7 @@ public function process($jsLayout) $fields ); } + return $jsLayout; } @@ -304,9 +314,6 @@ private function getBillingAddressComponent($paymentCode, $elements) 'checkoutProvider', 'billingAddress' . $paymentCode, [ - 'country_id' => [ - 'sortOrder' => 115, - ], 'region' => [ 'visible' => false, ], diff --git a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php index 369ae8e6f725e..cbbbd9a9b4d01 100644 --- a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php +++ b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php @@ -6,28 +6,38 @@ namespace Magento\Checkout\Model; +use Magento\Checkout\Api\Data\PaymentDetailsInterface; +use Magento\Checkout\Api\Data\ShippingInformationInterface; +use Magento\Checkout\Api\ShippingInformationManagementInterface; +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\InputException; -use Magento\Framework\Exception\StateException; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\StateException; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\CartTotalRepositoryInterface; use Magento\Quote\Api\Data\AddressInterface; +use Magento\Quote\Api\Data\CartExtensionFactory; use Magento\Quote\Api\Data\CartInterface; -use Psr\Log\LoggerInterface as Logger; +use Magento\Quote\Api\PaymentMethodManagementInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\TotalsCollector; use Magento\Quote\Model\QuoteAddressValidator; -use Magento\Quote\Api\Data\CartExtensionFactory; use Magento\Quote\Model\ShippingAssignmentFactory; use Magento\Quote\Model\ShippingFactory; -use Magento\Framework\App\ObjectManager; +use Psr\Log\LoggerInterface as Logger; /** - * Class ShippingInformationManagement + * Class checkout shipping information management * - * @package Magento\Checkout\Model * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInformationManagementInterface +class ShippingInformationManagement implements ShippingInformationManagementInterface { /** - * @var \Magento\Quote\Api\PaymentMethodManagementInterface + * @var PaymentMethodManagementInterface */ protected $paymentMethodManagement; @@ -37,12 +47,12 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf protected $paymentDetailsFactory; /** - * @var \Magento\Quote\Api\CartTotalRepositoryInterface + * @var CartTotalRepositoryInterface */ protected $cartTotalsRepository; /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ protected $quoteRepository; @@ -57,65 +67,63 @@ class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInf protected $addressValidator; /** - * @var \Magento\Customer\Api\AddressRepositoryInterface + * @var AddressRepositoryInterface * @deprecated 100.2.0 */ protected $addressRepository; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface * @deprecated 100.2.0 */ protected $scopeConfig; /** - * @var \Magento\Quote\Model\Quote\TotalsCollector + * @var TotalsCollector * @deprecated 100.2.0 */ protected $totalsCollector; /** - * @var \Magento\Quote\Api\Data\CartExtensionFactory + * @var CartExtensionFactory */ private $cartExtensionFactory; /** - * @var \Magento\Quote\Model\ShippingAssignmentFactory + * @var ShippingAssignmentFactory */ protected $shippingAssignmentFactory; /** - * @var \Magento\Quote\Model\ShippingFactory + * @var ShippingFactory */ private $shippingFactory; /** - * Constructor - * - * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement - * @param \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory - * @param \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Quote\Model\QuoteAddressValidator $addressValidator + * @param PaymentMethodManagementInterface $paymentMethodManagement + * @param PaymentDetailsFactory $paymentDetailsFactory + * @param CartTotalRepositoryInterface $cartTotalsRepository + * @param CartRepositoryInterface $quoteRepository + * @param QuoteAddressValidator $addressValidator * @param Logger $logger - * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector + * @param AddressRepositoryInterface $addressRepository + * @param ScopeConfigInterface $scopeConfig + * @param TotalsCollector $totalsCollector * @param CartExtensionFactory|null $cartExtensionFactory * @param ShippingAssignmentFactory|null $shippingAssignmentFactory * @param ShippingFactory|null $shippingFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, - \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory, - \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository, - \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, + PaymentMethodManagementInterface $paymentMethodManagement, + PaymentDetailsFactory $paymentDetailsFactory, + CartTotalRepositoryInterface $cartTotalsRepository, + CartRepositoryInterface $quoteRepository, QuoteAddressValidator $addressValidator, Logger $logger, - \Magento\Customer\Api\AddressRepositoryInterface $addressRepository, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector, + AddressRepositoryInterface $addressRepository, + ScopeConfigInterface $scopeConfig, + TotalsCollector $totalsCollector, CartExtensionFactory $cartExtensionFactory = null, ShippingAssignmentFactory $shippingAssignmentFactory = null, ShippingFactory $shippingFactory = null @@ -141,24 +149,23 @@ public function __construct( * Save address information. * * @param int $cartId - * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation - * @return \Magento\Checkout\Api\Data\PaymentDetailsInterface + * @param ShippingInformationInterface $addressInformation + * @return PaymentDetailsInterface * @throws InputException * @throws NoSuchEntityException * @throws StateException */ public function saveAddressInformation( $cartId, - \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation - ) { - /** @var \Magento\Quote\Model\Quote $quote */ + ShippingInformationInterface $addressInformation + ): PaymentDetailsInterface { + /** @var Quote $quote */ $quote = $this->quoteRepository->getActive($cartId); $this->validateQuote($quote); $address = $addressInformation->getShippingAddress(); - if (!$address || !$address->getCountryId()) { - throw new StateException(__('The shipping address is missing. Set the address and try again.')); - } + $this->validateAddress($address); + if (!$address->getCustomerAddressId()) { $address->setCustomerAddressId(null); } @@ -182,6 +189,14 @@ public function saveAddressInformation( $quote->setIsMultiShipping(false); $this->quoteRepository->save($quote); + } catch (LocalizedException $e) { + $this->logger->critical($e); + throw new InputException( + __( + 'The shipping information was unable to be saved. Error: "%message"', + ['message' => $e->getMessage()] + ) + ); } catch (\Exception $e) { $this->logger->critical($e); throw new InputException( @@ -199,26 +214,39 @@ public function saveAddressInformation( ); } - /** @var \Magento\Checkout\Api\Data\PaymentDetailsInterface $paymentDetails */ + /** @var PaymentDetailsInterface $paymentDetails */ $paymentDetails = $this->paymentDetailsFactory->create(); $paymentDetails->setPaymentMethods($this->paymentMethodManagement->getList($cartId)); $paymentDetails->setTotals($this->cartTotalsRepository->get($cartId)); return $paymentDetails; } + /** + * Validate shipping address + * + * @param AddressInterface|null $address + * @return void + * @throws StateException + */ + private function validateAddress(?AddressInterface $address): void + { + if (!$address || !$address->getCountryId()) { + throw new StateException(__('The shipping address is missing. Set the address and try again.')); + } + } + /** * Validate quote * - * @param \Magento\Quote\Model\Quote $quote + * @param Quote $quote * @throws InputException - * @throws NoSuchEntityException * @return void */ - protected function validateQuote(\Magento\Quote\Model\Quote $quote) + protected function validateQuote(Quote $quote): void { - if (0 == $quote->getItemsCount()) { + if (!$quote->getItemsCount()) { throw new InputException( - __("The shipping method can't be set for an empty cart. Add an item to cart and try again.") + __('The shipping method can\'t be set for an empty cart. Add an item to cart and try again.') ); } } @@ -231,7 +259,7 @@ protected function validateQuote(\Magento\Quote\Model\Quote $quote) * @param string $method * @return CartInterface */ - private function prepareShippingAssignment(CartInterface $quote, AddressInterface $address, $method) + private function prepareShippingAssignment(CartInterface $quote, AddressInterface $address, $method): CartInterface { $cartExtension = $quote->getExtensionAttributes(); if ($cartExtension === null) { diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup.xml new file mode 100644 index 0000000000000..32e529fb7ca0a --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup.xml @@ -0,0 +1,31 @@ +<?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="AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup"> + <annotations> + <description>Check address data in Estimate Shipping And Tax section of shopping cart on storefront</description> + </annotations> + <arguments> + <argument name="country" type="string" defaultValue="{{US_Address_TX.country}}"/> + <argument name="state" type="string" defaultValue="{{US_Address_TX.state}}"/> + <argument name="postcode" type="string" defaultValue="{{US_Address_TX.postcode}}"/> + </arguments> + + <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalVisible"/> + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingAndTaxIfNeeded" /> + <seeOptionIsSelected selector="{{CheckoutCartSummarySection.country}}" userInput="{{country}}" stepKey="checkCountry"/> + <seeOptionIsSelected selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{state}}" stepKey="checkState" /> + <grabValueFrom selector="{{CheckoutCartSummarySection.postcode}}" stepKey="grabPostCodeText"/> + <assertEquals message="Address postcode is invalid" stepKey="checkPostcode"> + <expectedResult type="string">{{postcode}}</expectedResult> + <actualResult type="variable">grabPostCodeText</actualResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml index fa4db86a5860d..47e44e86affb8 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartItemsActionGroup.xml @@ -19,10 +19,10 @@ <argument name="subtotal" type="string"/> <argument name="qty" type="string"/> </arguments> - + <see selector="{{CheckoutCartProductSection.productName}}" userInput="{{productName}}" stepKey="seeProductNameInCheckoutSummary"/> - <see selector="{{CheckoutCartProductSection.checkoutCartProductPrice}}" userInput="{{productPrice}}" stepKey="seeProductPriceInCart"/> - <see selector="{{CheckoutCartProductSection.checkoutCartSubtotal}}" userInput="{{subtotal}}" stepKey="seeSubtotalPrice"/> - <seeInField selector="{{CheckoutCartProductSection.qtyByContains(productSku)}}" userInput="{{qty}}" stepKey="seeProductQuantity"/> + <see selector="{{CheckoutCartProductSection.ProductPriceByName(productName)}}" userInput="{{productPrice}}" stepKey="seeProductPriceInCart"/> + <see selector="{{CheckoutCartProductSection.productSubtotalByName(productName)}}" userInput="{{subtotal}}" stepKey="seeSubtotalPrice"/> + <seeInField selector="{{CheckoutCartProductSection.ProductQuantityByName(productName)}}" userInput="{{qty}}" stepKey="seeProductQuantity"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml new file mode 100644 index 0000000000000..18fc6fac18085 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml @@ -0,0 +1,17 @@ +<?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="AssertStorefrontOrderIsNotPlacedActionGroup" extends="AssertStorefrontOrderCannotBePlacedActionGroup"> + <annotations> + <description>Validates order cannot be placed and checks error message.</description> + </annotations> + <remove keyForRemoval="assertErrorMessage"/> + <seeElementInDOM selector="{{CheckoutHeaderSection.errorMessageContainsText(error)}}" stepKey="assertErrorMessageInDOM"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup.xml new file mode 100644 index 0000000000000..543b6bc8cb599 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup.xml @@ -0,0 +1,28 @@ +<?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="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup"> + <annotations> + <description>Fill address data in Estimate Shipping And Tax section of shopping cart on storefront</description> + </annotations> + <arguments> + <argument name="country" type="string" defaultValue="{{US_Address_TX.country}}"/> + <argument name="state" type="string" defaultValue="{{US_Address_TX.state}}"/> + <argument name="postcode" type="string" defaultValue="{{US_Address_TX.postcode}}"/> + </arguments> + + <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.estimateShippingAndTaxSummary}}" visible="false" stepKey="openEestimateShippingAndTaxSection"/> + <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="{{country}}" stepKey="selectCountry"/> + <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{state}}" stepKey="selectState"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.postcode}}" stepKey="waitForPostCodeVisible"/> + <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="{{postcode}}" stepKey="selectPostCode"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDiappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml new file mode 100644 index 0000000000000..1e86becdc0888 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml @@ -0,0 +1,18 @@ +<?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="StorefrontCheckoutClickNextOnShippingStepActionGroup" extends="StorefrontCheckoutForwardFromShippingStepActionGroup"> + <annotations> + <description>Scrolls and clicks next on Checkout Shipping step</description> + </annotations> + <scrollTo selector="{{CheckoutShippingSection.next}}" before="clickNext" stepKey="scrollToNextButton"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCustomerAddressesOnPaymentStepInCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCustomerAddressesOnPaymentStepInCheckoutActionGroup.xml new file mode 100644 index 0000000000000..2ca395cbf6d25 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenCustomerAddressesOnPaymentStepInCheckoutActionGroup.xml @@ -0,0 +1,20 @@ +<?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="StorefrontOpenCustomerAddressesOnPaymentStepInCheckoutActionGroup"> + <annotations> + <description>Click 'Change Address' link on the Storefront Checkout page on the 'Payment' step.</description> + </annotations> + + <click selector="{{CheckoutBillingAddressSection.changeAddressButton}}" stepKey="clickChangeAddresslink"/> + <waitForElementVisible selector="{{CheckoutShippingAddressSearchSection.popupSelectShippingAddress}}" stepKey="seePopup"/> + <seeElement selector="{{CheckoutShippingAddressSearchSection.selectShippingAddressGrid}}" stepKey="seeAddressGrid"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml index 4203aa35a3bdb..1dc0b743bdd16 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontOpenMiniCartActionGroup.xml @@ -8,6 +8,18 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="clickViewAndEditCartFromMiniCartActionGroup"> + <annotations> + <description>Clicks on the Storefront Mini Shopping Cart icon. Clicks on the 'View and Edit Cart' link. Validates that the URL is present and correct. PLEASE NOTE: The URL is Hardcoded.</description> + </annotations> + + <scrollTo selector="{{StorefrontMinicartSection.showCart}}" stepKey="scrollToMiniCart"/> + <conditionalClick selector="{{StorefrontMinicartSection.showCart}}" dependentSelector="{{StorefrontMinicartSection.miniCartOpened}}" visible="false" stepKey="openMiniCart"/> + <waitForElementVisible selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="waitForViewAndEditCartVisible"/> + <click selector="{{StorefrontMinicartSection.viewAndEditCart}}" stepKey="viewAndEditCart"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeInCurrentUrl url="checkout/cart" stepKey="seeInCurrentUrl"/> + </actionGroup> <actionGroup name="StorefrontOpenMiniCartActionGroup"> <annotations> <description>Clicks on the Mini Shopping Cart icon in the Storefront Header.</description> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSearchAddressInSelectBillingAddressPopupOnPaymentStepOnCheckoutActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSearchAddressInSelectBillingAddressPopupOnPaymentStepOnCheckoutActionGroup.xml new file mode 100644 index 0000000000000..845e0b7733fca --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontSearchAddressInSelectBillingAddressPopupOnPaymentStepOnCheckoutActionGroup.xml @@ -0,0 +1,24 @@ +<?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="StorefrontSearchAddressInSelectBillingAddressPopupOnPaymentStepOnCheckoutActionGroup"> + <annotations> + <description>Search customer address in 'Select Billing Address' popup on the Storefront Checkout on the 'Payment' step.</description> + </annotations> + <arguments> + <argument name="addressSearchTerm" type="string" defaultValue="10001"/> + </arguments> + + <fillField selector="{{CheckoutBillingAddressSearchSection.searchAddressField}}" userInput="{{addressSearchTerm}}" stepKey="fillAddressInSearchField"/> + <click selector="{{CheckoutBillingAddressSearchSection.searchAddressButton}}" stepKey="clickSearchAddressButton"/> + <see selector="{{CheckoutBillingAddressSearchSection.addressesFound}}" userInput="1 addresses" stepKey="assertOneAddressesWasFound"/> + <see selector="{{CheckoutBillingAddressSearchSection.firstBillingAddressItem}}" userInput="{{addressSearchTerm}}" stepKey="verifyAddresses"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutHeaderSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutHeaderSection.xml index babbe51746df8..615db79b2ba6d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutHeaderSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutHeaderSection.xml @@ -9,5 +9,6 @@ <section name="CheckoutHeaderSection"> <element name="shippingMethodStep" type="text" selector=".opc-progress-bar-item:nth-of-type(1)"/> <element name="reviewAndPaymentsStep" type="text" selector=".opc-progress-bar-item:nth-of-type(2)"/> + <element name="errorMessageContainsText" type="text" selector="//div[contains(@class, 'message message-error error')]//div[contains(text(), '{{text}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml index 31a9d011a91c7..a9c3d20c447a9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml @@ -37,7 +37,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Add product to cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/CheckCheckoutSuccessPageTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/CheckCheckoutSuccessPageTest.xml index 5f898492ad016..b939209751fcd 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/CheckCheckoutSuccessPageTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/CheckCheckoutSuccessPageTest.xml @@ -30,7 +30,7 @@ <!--Logout from customer account--> <amOnPage url="{{StorefrontCustomerLogoutPage.url}}" stepKey="logoutCustomerOne"/> <waitForPageLoad stepKey="waitLogoutCustomerOne"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> </after> @@ -147,7 +147,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> </after> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutSpecificDestinationsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutSpecificDestinationsTest.xml index 1bfb1804f41a7..294fc2c562491 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutSpecificDestinationsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutSpecificDestinationsTest.xml @@ -77,7 +77,7 @@ </actionGroup> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="defaultCategory" stepKey="deleteCategory"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml index aea0657cc2e3b..899688c80764e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ConfiguringInstantPurchaseFunctionalityTest.xml @@ -47,7 +47,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create store views --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml index 891f647e3d5ef..9d092b4b84a3c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteConfigurableProductFromShoppingCartTest.xml @@ -60,6 +60,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add configurable product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml index f2501fdf4c0c6..c88025feba3d4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml @@ -30,7 +30,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml index b072989bc968c..600163501b556 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml @@ -30,7 +30,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml index 9b0da574d6307..661957a1de980 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml @@ -30,7 +30,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer Log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml index 80cf9c14b578e..43ee1c8dd3de4 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml @@ -30,7 +30,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer Log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 797172de5de45..4a4428712ac9d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -111,6 +111,9 @@ <!-- Logout customer --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Simple Product to cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontCheckCustomerInfoCreatedByGuestTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontCheckCustomerInfoCreatedByGuestTest.xml index c08a930ba6224..d0fb6babb22fa 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontCheckCustomerInfoCreatedByGuestTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontCheckCustomerInfoCreatedByGuestTest.xml @@ -31,7 +31,7 @@ <after> <deleteData createDataKey="product" stepKey="deleteProduct" /> <deleteData createDataKey="category" stepKey="deleteCategory" /> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="$$product.name$$.html" stepKey="navigateToProductPage"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontFreeShippingRecalculationAfterCouponCodeAddedTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontFreeShippingRecalculationAfterCouponCodeAddedTest.xml index 8a2990c5869c9..d7b462d7f649b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontFreeShippingRecalculationAfterCouponCodeAddedTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StoreFrontFreeShippingRecalculationAfterCouponCodeAddedTest.xml @@ -54,7 +54,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCartPriceRule"> <argument name="ruleName" value="{{CatPriceRule.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="ApplyCartRuleOnStorefrontActionGroup" stepKey="applyCartRule"> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml index e716ba294f578..7d91b13b7b833 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddConfigurableProductToShoppingCartTest.xml @@ -120,6 +120,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Configurable Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml index 3c1421f2616aa..e098c15c0eb6a 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontAddDownloadableProductToShoppingCartTest.xml @@ -34,7 +34,7 @@ <after> <magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/> <deleteData createDataKey="createDownloadableProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Downloadable Product page --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml index 5e13ce3e06e10..58cc137efd7b3 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml @@ -38,7 +38,7 @@ <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Storefront as Guest and add simple product to cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml index 92eae461019a2..80da3fb70f944 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndProductWithTierPricesTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> <argument name="customerEmail" value="UKCustomer.email"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml index 2f19dcd2dc32f..85e6a6b9c434c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithDifferentShippingAndBillingAddressAndRegisterCustomerAfterCheckoutTest.xml @@ -31,7 +31,7 @@ <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteCustomer"> <argument name="customerEmail" value="UKCustomer.email"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml index a9db81620d329..c76ec4cbc3c5c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml @@ -101,7 +101,10 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml index 1c3d3d4914fb4..f0907e89f00da 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml @@ -35,7 +35,7 @@ <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index 8bdbabb584b83..580b4e32b0b28 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -31,7 +31,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteSimpleCategory"/> <deleteData createDataKey="createCustomer" stepKey="deleteUsCustomer"/> <actionGroup ref="AdminClearCustomersFiltersActionGroup" stepKey="resetCustomerFilters"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </after> @@ -144,7 +144,7 @@ <argument name="name" value="{{SimpleTaxCA.state}}-{{SimpleTaxCA.rate}}"/> <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="simpleproduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simplecategory" stepKey="deleteCategory"/> <deleteData createDataKey="multiple_address_customer" stepKey="deleteCustomer"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml index e0fff27a583e7..2b96d385487bc 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithNewCustomerRegistrationAndDisableGuestCheckoutTest.xml @@ -35,7 +35,7 @@ <actionGroup ref="StorefrontSignOutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithoutRegionTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithoutRegionTest.xml index a6b9372679a11..c66c6371ae595 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithoutRegionTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutWithoutRegionTest.xml @@ -33,7 +33,7 @@ <actionGroup ref="SelectCountriesWithRequiredRegionActionGroup" stepKey="setDefaultCountriesWithRequiredRegion"> <argument name="countries" value="DefaultCountriesWithRequiredRegions"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerLoginDuringCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerLoginDuringCheckoutTest.xml index afefbff5ea59a..f43cadabfd611 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerLoginDuringCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerLoginDuringCheckoutTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Logout admin --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Storefront as Guest and create new account --> <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="createNewCustomerAccount"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteBundleProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteBundleProductFromMiniShoppingCartTest.xml index 8956ed7687f06..1690612fa3242 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteBundleProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteBundleProductFromMiniShoppingCartTest.xml @@ -46,7 +46,7 @@ <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="createSubCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml index 34264e5982651..8fe2ac3a74791 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml @@ -71,7 +71,10 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Add Configurable Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteDownloadableProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteDownloadableProductFromMiniShoppingCartTest.xml index dd9259833cbc4..a60fe104ce14b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteDownloadableProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteDownloadableProductFromMiniShoppingCartTest.xml @@ -33,7 +33,7 @@ <after> <magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/> <deleteData createDataKey="createDownloadableProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Downloadable Product page --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteProductsWithCartItemsDisplayDefaultLimitationFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteProductsWithCartItemsDisplayDefaultLimitationFromMiniShoppingCartTest.xml index 07215988c945d..992d3eab9b563 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteProductsWithCartItemsDisplayDefaultLimitationFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteProductsWithCartItemsDisplayDefaultLimitationFromMiniShoppingCartTest.xml @@ -63,7 +63,7 @@ <deleteData createDataKey="simpleProduct8" stepKey="deleteProduct8"/> <deleteData createDataKey="simpleProduct9" stepKey="deleteProduct9"/> <deleteData createDataKey="simpleProduct10" stepKey="deleteProduct10"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product1 page in StoreFront--> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleAndVirtualProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleAndVirtualProductFromMiniShoppingCartTest.xml index b1aa1de71293f..a6ac6d40a0ce0 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleAndVirtualProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleAndVirtualProductFromMiniShoppingCartTest.xml @@ -32,7 +32,7 @@ <after> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="virtualProduct" stepKey="deleteVirtualproduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Add Simple Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleProductFromMiniShoppingCartTest.xml index 0108b6310f59d..9e0f59f8a0e77 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteSimpleProductFromMiniShoppingCartTest.xml @@ -27,7 +27,7 @@ </before> <after> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Add Simple Product to the cart --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutTest.xml index a2007da317c00..cce4d9f0345d7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutTest.xml @@ -29,7 +29,7 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> </after> @@ -114,7 +114,7 @@ <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <magentoCLI stepKey="allowSpecificValue" command="config:set payment/checkmo/allowspecific 0" /> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml index b800ef758d65e..3fe5f1be2a53d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -108,7 +108,10 @@ <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule1"/> <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> <createData entity="DefaultMinimumOrderAmount" stepKey="defaultMinimumOrderAmount"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create a Tax Rule --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml index 97004ea91f5fd..c217eca5053c1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml @@ -27,7 +27,7 @@ <after> <deleteData createDataKey="virtualProduct" stepKey="deleteVirtualProduct"/> <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml index f11d25a30f073..d83550a82a87c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml @@ -16,10 +16,7 @@ <severity value="MAJOR"/> <testCaseId value="MC-22625"/> <useCaseId value="MC-21926"/> - <group value="Checkout"/> - <skip> - <issueId value="MC-29597"/> - </skip> + <group value="checkout"/> </annotations> <before> @@ -27,22 +24,26 @@ <magentoCLI command="config:set {{AdminFreeshippingActiveConfigData.path}} {{AdminFreeshippingActiveConfigData.enabled}}" stepKey="enableFreeShippingMethod" /> <magentoCLI command="config:set {{AdminFreeshippingMinimumOrderAmountConfigData.path}} {{AdminFreeshippingMinimumOrderAmountConfigData.hundred}}" stepKey="setFreeShippingMethodMinimumOrderAmountToBe100" /> + <!--Set Fedex configs data--> + <magentoCLI command="config:set {{AdminFedexEnableForCheckoutConfigData.path}} {{AdminFedexEnableForCheckoutConfigData.value}}" stepKey="enableCheckout"/> + <magentoCLI command="config:set {{AdminFedexEnableSandboxModeConfigData.path}} {{AdminFedexEnableSandboxModeConfigData.value}}" stepKey="enableSandbox"/> + <magentoCLI command="config:set {{AdminFedexEnableDebugConfigData.path}} {{AdminFedexEnableDebugConfigData.value}}" stepKey="enableDebug"/> + <magentoCLI command="config:set {{AdminFedexEnableShowMethodConfigData.path}} {{AdminFedexEnableShowMethodConfigData.value}}" stepKey="enableShowMethod"/> + <!--Set StoreInformation configs data--> - <magentoCLI command="config:set {{AdminGeneralSetStoreNameConfigData.path}} '{{AdminGeneralSetStoreNameConfigData.value}}'" stepKey="setStoreInformationName"/> - <magentoCLI command="config:set {{AdminGeneralSetStorePhoneConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.telephone}}" stepKey="setStoreInformationPhone"/> - <magentoCLI command="config:set {{AdminGeneralSetCountryConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.country_id}}" stepKey="setStoreInformationCountry"/> - <magentoCLI command="config:set {{AdminGeneralSetCityConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.city}}" stepKey="setStoreInformationCity"/> - <magentoCLI command="config:set {{AdminGeneralSetPostcodeConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.postcode}}" stepKey="setStoreInformationPostcode"/> - <magentoCLI command="config:set {{AdminGeneralSetStreetAddressConfigData.path}} '{{DE_Address_Berlin_Not_Default_Address.street[0]}}'" stepKey="setStoreInformationStreetAddress"/> - <magentoCLI command="config:set {{AdminGeneralSetStreetAddress2ConfigData.path}} '{{US_Address_California.street[0]}}'" stepKey="setStoreInformationStreetAddress2"/> - <magentoCLI command="config:set {{AdminGeneralSetVatNumberConfigData.path}} {{AdminGeneralSetVatNumberConfigData.value}}" stepKey="setStoreInformationVatNumber"/> + <actionGroup ref="AdminSetStoreInformationConfigurationActionGroup" stepKey="setStoreInformationConfigData"> + <argument name="telephone" value="{{DE_Address_Berlin_Not_Default_Address.telephone}}"/> + <argument name="country" value="{{DE_Address_Berlin_Not_Default_Address.country_id}}"/> + <argument name="state" value="{{DE_Address_Berlin_Not_Default_Address.state}}"/> + <argument name="city" value="{{DE_Address_Berlin_Not_Default_Address.city}}"/> + <argument name="postcode" value="{{DE_Address_Berlin_Not_Default_Address.postcode}}"/> + <argument name="street" value="{{DE_Address_Berlin_Not_Default_Address.street[0]}}"/> + </actionGroup> <!--Set Shipping settings origin data--> - <magentoCLI command="config:set {{AdminShippingSettingsOriginCountryConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.country_id}}" stepKey="setOriginCountry"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginCityConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.city}}" stepKey="setOriginCity"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginZipCodeConfigData.path}} {{DE_Address_Berlin_Not_Default_Address.postcode}}" stepKey="setOriginZipCode"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddressConfigData.path}} '{{DE_Address_Berlin_Not_Default_Address.street[0]}}'" stepKey="setOriginStreetAddress"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddress2ConfigData.path}} '{{US_Address_California.street[0]}}'" stepKey="setOriginStreetAddress2"/> + <actionGroup ref="AdminSetShippingOriginConfigurationActionGroup" stepKey="setShippingOriginConfigurationData"> + <argument name="address" value="DE_Address_Berlin_Not_Default_Address"/> + </actionGroup> <!-- Create Simple Product --> <createData entity="defaultSimpleProduct" stepKey="createSimpleProduct"> @@ -56,9 +57,6 @@ </createData> <!-- Create Customer with filled Shipping & Billing Address --> <createData entity="CustomerEntityOne" stepKey="createCustomer"/> - - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> <after> @@ -69,19 +67,23 @@ <magentoCLI command="config:set {{AdminFreeshippingMinimumOrderAmountConfigData.path}} {{AdminFreeshippingMinimumOrderAmountConfigData.default}}" stepKey="setFreeShippingMethodMinimumOrderAmountAsDefault" /> <magentoCLI command="config:set {{AdminFreeshippingActiveConfigData.path}} {{AdminFreeshippingActiveConfigData.disabled}}" stepKey="disableFreeShippingMethod" /> <!--Reset configs--> - <magentoCLI command="config:set {{AdminGeneralSetStoreNameConfigData.path}} ''" stepKey="setStoreInformationName"/> - <magentoCLI command="config:set {{AdminGeneralSetStorePhoneConfigData.path}} ''" stepKey="setStoreInformationPhone"/> - <magentoCLI command="config:set {{AdminGeneralSetCityConfigData.path}} ''" stepKey="setStoreInformationCity"/> - <magentoCLI command="config:set {{AdminGeneralSetPostcodeConfigData.path}} ''" stepKey="setStoreInformationPostcode"/> - <magentoCLI command="config:set {{AdminGeneralSetStreetAddressConfigData.path}} ''" stepKey="setStoreInformationStreetAddress"/> - <magentoCLI command="config:set {{AdminGeneralSetStreetAddress2ConfigData.path}} ''" stepKey="setStoreInformationStreetAddress2"/> - <magentoCLI command="config:set {{AdminGeneralSetVatNumberConfigData.path}} ''" stepKey="setStoreInformationVatNumber"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginCityConfigData.path}} ''" stepKey="setOriginCity"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginZipCodeConfigData.path}} ''" stepKey="setOriginZipCode"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddressConfigData.path}} ''" stepKey="setOriginStreetAddress"/> - <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddress2ConfigData.path}} ''" stepKey="setOriginStreetAddress2"/> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <magentoCLI command="config:set {{AdminFedexDisableForCheckoutConfigData.path}} {{AdminFedexDisableForCheckoutConfigData.value}}" stepKey="disableCheckout"/> + <magentoCLI command="config:set {{AdminFedexDisableSandboxModeConfigData.path}} {{AdminFedexDisableSandboxModeConfigData.value}}" stepKey="disableSandbox"/> + <magentoCLI command="config:set {{AdminFedexDisableDebugConfigData.path}} {{AdminFedexDisableDebugConfigData.value}}" stepKey="disableDebug"/> + <magentoCLI command="config:set {{AdminFedexDisableShowMethodConfigData.path}} {{AdminFedexDisableShowMethodConfigData.value}}" stepKey="disableShowMethod"/> + <actionGroup ref="AdminResetShippingOriginConfigurationActionGroup" stepKey="resetShippingOriginConfig"/> + <actionGroup ref="AdminSetStoreInformationConfigurationActionGroup" stepKey="resetStoreInformationConfig"> + <argument name="storeName" value=""/> + <argument name="storeHoursOfOperation" value=""/> + <argument name="vatNumber" value=""/> + <argument name="telephone" value=""/> + <argument name="country" value=""/> + <argument name="state" value=""/> + <argument name="city" value=""/> + <argument name="postcode" value=""/> + <argument name="street" value=""/> + </actionGroup> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!-- Guest Customer Test Scenario --> @@ -105,7 +107,7 @@ </actionGroup> <!-- Go to Order review --> - <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToCheckoutReview"/> + <actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="goToCheckoutReview"/> <!-- Checkout select Check/Money Order payment --> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> @@ -122,7 +124,7 @@ <actionGroup ref="AssertStorefrontNotCalculatedValueInShippingTotalInOrderSummaryActionGroup" stepKey="assertNotYetCalculated"/> <!-- Assert order cannot be placed and error message will shown. --> - <actionGroup ref="AssertStorefrontOrderCannotBePlacedActionGroup" stepKey="assertOrderCannotBePlaced"> + <actionGroup ref="AssertStorefrontOrderIsNotPlacedActionGroup" stepKey="assertOrderCannotBePlaced"> <argument name="error" value="The shipping method is missing. Select the shipping method and try again."/> </actionGroup> @@ -135,7 +137,7 @@ </actionGroup> <!-- Go to Order review --> - <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToCheckoutReview2"/> + <actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="goToCheckoutOrderReview"/> <!-- Place order assert succeed --> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="checkoutPlaceOrder"/> @@ -147,53 +149,52 @@ </actionGroup> <!-- Add Simple Product to Cart --> - <actionGroup ref="StorefrontAddSimpleProductToShoppingCartActionGroup" stepKey="addProductToCart2"> + <actionGroup ref="StorefrontAddSimpleProductToShoppingCartActionGroup" stepKey="addSimpleProductToCart"> <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> <!-- Go to Checkout --> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckout2"/> - + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="proceedToCheckout"/> <!-- Select Free Shipping --> - <actionGroup ref="StorefrontSetShippingMethodActionGroup" stepKey="setShippingMethodFreeShipping2"> + <actionGroup ref="StorefrontSetShippingMethodActionGroup" stepKey="selectFreeShippingMethod"> <argument name="shippingMethodName" value="Free Shipping"/> </actionGroup> <!-- Go to Order review --> - <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToCheckoutReview3"/> + <actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="goToCheckoutPaymentPage"/> <!-- Checkout select Check/Money Order payment --> - <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment2"/> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPaymentMethod"/> <!-- Select payment solution --> - <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution2" /> - <waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton2"/> + <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="checkBillingAddressNotSameCheckbox"/> + <waitForElementVisible selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButtonVisible"/> <!-- Apply Discount Coupon to the Order --> - <actionGroup ref="StorefrontApplyDiscountCodeActionGroup" stepKey="applyDiscountCoupon2"> + <actionGroup ref="StorefrontApplyDiscountCodeActionGroup" stepKey="applyDiscountCouponCode"> <argument name="discountCode" value="$createCartPriceRuleCoupon.code$"/> </actionGroup> <!-- Assert Shipping total is not yet calculated --> - <actionGroup ref="AssertStorefrontNotCalculatedValueInShippingTotalInOrderSummaryActionGroup" stepKey="assertNotYetCalculated2"/> + <actionGroup ref="AssertStorefrontNotCalculatedValueInShippingTotalInOrderSummaryActionGroup" stepKey="assertShippingTotalNotYetCalculated"/> - <!-- Assert order cannot be placed and error message will shown. --> - <actionGroup ref="AssertStorefrontOrderCannotBePlacedActionGroup" stepKey="assertOrderCannotBePlaced2"> + <!-- Assert order cannot be placed and error message will shown. --> + <actionGroup ref="AssertStorefrontOrderIsNotPlacedActionGroup" stepKey="assertOrderIsNotPlaced"> <argument name="error" value="The shipping method is missing. Select the shipping method and try again."/> </actionGroup> <!-- Go to checkout page --> - <actionGroup ref="OpenStoreFrontCheckoutShippingPageActionGroup" stepKey="openCheckoutShippingPage2"/> + <actionGroup ref="OpenStoreFrontCheckoutShippingPageActionGroup" stepKey="goToCheckoutShippingPage"/> <!-- Chose flat rate --> - <actionGroup ref="StorefrontSetShippingMethodActionGroup" stepKey="setShippingMethodFlatRate2"> + <actionGroup ref="StorefrontSetShippingMethodActionGroup" stepKey="selectFlatRateShippingMethod"> <argument name="shippingMethodName" value="Flat Rate"/> </actionGroup> <!-- Go to Order review --> - <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToCheckoutReview4"/> + <actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="goToCheckoutPaymentStep"/> <!-- Place order assert succeed --> - <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="checkoutPlaceOrder2"/> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="placeOrder"/> </test> </tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml index ae7b8d2446380..e335caa2ddb64 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml @@ -21,6 +21,8 @@ <before> <!--Create a product--> <createData entity="SimpleProduct2" stepKey="createProduct"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!--Delete created data--> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml index b678cb835f503..1fff7501f578d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml @@ -32,7 +32,7 @@ <argument name="customStore" value="customStore"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create store view --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml index e87aa31576595..44e12d1ea4039 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductQuantityChangesInBackendAfterCustomerCheckoutTest.xml @@ -28,7 +28,7 @@ <after> <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="enableGuestCheckout"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontRefreshPageDuringGuestCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontRefreshPageDuringGuestCheckoutTest.xml index bb74726330b68..90896c3eb403e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontRefreshPageDuringGuestCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontRefreshPageDuringGuestCheckoutTest.xml @@ -30,7 +30,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <!-- Logout admin --> - <actionGroup ref="logout" stepKey="logoutAsAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAsAdmin"/> </after> <!-- Add simple product to cart as Guest --> <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml index b53954709b2de..293abcb8197e1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml @@ -44,7 +44,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Downloadable Product page --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml index ba096d4a59615..04ee2e2adbf28 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKGuestCheckoutWithConditionProductQuantityEqualsToOrderedQuantityTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml index e67fd938c0a74..bb3bd50072f23 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUSCustomerCheckoutWithCouponAndBankTransferPaymentMethodTest.xml @@ -32,7 +32,7 @@ <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="disableBankTransferPayment"/> <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Product page in StoreFront and assert product and price range --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdatePriceInShoppingCartAfterProductSaveTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdatePriceInShoppingCartAfterProductSaveTest.xml index 4bff22950174f..46c4abf4eab1a 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdatePriceInShoppingCartAfterProductSaveTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUpdatePriceInShoppingCartAfterProductSaveTest.xml @@ -31,7 +31,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <actionGroup ref="SetCustomerDataLifetimeActionGroup" stepKey="setDefaultCustomerDataLifetime"/> <magentoCLI command="indexer:reindex customer_grid" stepKey="reindexCustomerGrid"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to product page--> <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToSimpleProductPage"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/ZeroSubtotalOrdersWithProcessingStatusTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/ZeroSubtotalOrdersWithProcessingStatusTest.xml index 0f0b98912de30..781253a707271 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/ZeroSubtotalOrdersWithProcessingStatusTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/ZeroSubtotalOrdersWithProcessingStatusTest.xml @@ -36,7 +36,7 @@ <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> <createData entity="DisableFreeShippingConfig" stepKey="disableFreeShippingConfig"/> <createData entity="DisablePaymentMethodsSettingConfig" stepKey="disablePaymentMethodsSettingConfig"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="simpleproduct" stepKey="deleteProduct"/> <deleteData createDataKey="simplecategory" stepKey="deleteCategory"/> </after> diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php index 31ca2a2033012..9fff4b622e596 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php @@ -10,14 +10,16 @@ use Magento\Checkout\Helper\Data; use Magento\Customer\Model\AttributeMetadataDataProvider; use Magento\Customer\Model\Options; - +use Magento\Shipping\Model\Config; +use Magento\Store\Model\StoreManagerInterface; use Magento\Ui\Component\Form\AttributeMapper; -use PHPUnit_Framework_MockObject_MockObject as MockObject; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** * LayoutProcessorTest covers a list of variations for checkout layout processor */ -class LayoutProcessorTest extends \PHPUnit\Framework\TestCase +class LayoutProcessorTest extends TestCase { /** * @var AttributeMetadataDataProvider|MockObject @@ -45,7 +47,7 @@ class LayoutProcessorTest extends \PHPUnit\Framework\TestCase private $layoutProcessor; /** - * @var MockObject + * @var StoreManagerInterface|MockObject */ private $storeManager; @@ -75,11 +77,11 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $shippingConfig = $this->getMockBuilder(\Magento\Shipping\Model\Config::class) + $shippingConfig = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() ->getMock(); - $this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); + $this->storeManager = $this->createMock(StoreManagerInterface::class); $this->layoutProcessor = new LayoutProcessor( $this->attributeDataProvider, @@ -109,10 +111,12 @@ public function testProcess() $this->attributeMerger->expects(static::exactly(2)) ->method('merge') - ->willReturnMap([ - ['payment1_1' => $this->getBillingComponent('payment1_1')], - ['payment2_1' => $this->getBillingComponent('payment2_1')], - ]); + ->willReturnMap( + [ + ['payment1_1' => $this->getBillingComponent('payment1_1')], + ['payment2_1' => $this->getBillingComponent('payment2_1')], + ] + ); $actual = $this->layoutProcessor->process($jsLayout); @@ -236,9 +240,6 @@ private function getLayoutData() private function getBillingComponent($paymentCode) { return [ - 'country_id' => [ - 'sortOrder' => 115, - ], 'region' => [ 'visible' => false, ], diff --git a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php index 93375bb884535..79c4b37fb1813 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php @@ -6,101 +6,136 @@ namespace Magento\Checkout\Test\Unit\Model; +use Magento\Checkout\Api\Data\PaymentDetailsInterface; +use Magento\Checkout\Api\Data\ShippingInformationInterface; +use Magento\Checkout\Model\PaymentDetailsFactory; +use Magento\Checkout\Model\ShippingInformationManagement; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\StateException; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\CartTotalRepositoryInterface; +use Magento\Quote\Api\Data\AddressInterface; +use Magento\Quote\Api\Data\CartExtension; +use Magento\Quote\Api\Data\CartExtensionFactory; +use Magento\Quote\Api\Data\PaymentMethodInterface; +use Magento\Quote\Api\Data\TotalsInterface; +use Magento\Quote\Api\PaymentMethodManagementInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\QuoteAddressValidator; +use Magento\Quote\Model\Shipping; +use Magento\Quote\Model\ShippingAssignment; +use Magento\Quote\Model\ShippingAssignmentFactory; +use Magento\Quote\Model\ShippingFactory; +use PHPUnit\Framework\MockObject\MockObject as MockObject; +use PHPUnit\Framework\TestCase; + /** + * Test for \Magento\Checkout\Model\ShippingInformationManagement. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) */ -class ShippingInformationManagementTest extends \PHPUnit\Framework\TestCase +class ShippingInformationManagementTest extends TestCase { + private const STUB_CART_ID = 100; + + private const STUB_ITEMS_COUNT = 99; + + private const STUB_CARRIER_CODE = 'carrier_code'; + + private const STUB_SHIPPING_METHOD = 'shipping_method'; + + private const STUB_ERROR_MESSAGE = 'error message'; + /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var ShippingInformationManagement */ - private $objectManager; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ObjectManager */ - protected $paymentMethodManagementMock; + private $objectManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var PaymentMethodManagementInterface|MockObject */ - protected $paymentDetailsFactoryMock; + private $paymentMethodManagementMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var PaymentDetailsFactory|MockObject */ - protected $cartTotalsRepositoryMock; + private $paymentDetailsFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CartTotalRepositoryInterface|MockObject */ - protected $quoteRepositoryMock; + private $cartTotalsRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CartRepositoryInterface|MockObject */ - protected $shippingAddressMock; + private $quoteRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Address|MockObject */ - protected $quoteMock; + private $shippingAddressMock; /** - * @var \Magento\Checkout\Model\ShippingInformationManagement + * @var Quote|MockObject */ - protected $model; + private $quoteMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ShippingAssignmentFactory|MockObject */ private $shippingAssignmentFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CartExtensionFactory|MockObject */ private $cartExtensionFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ShippingFactory|MockObject */ private $shippingFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CartExtension|MockObject */ private $cartExtensionMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ShippingAssignment|MockObject */ private $shippingAssignmentMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var QuoteAddressValidator|MockObject */ - private $shippingMock; + private $addressValidatorMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @inheritdoc */ - private $addressValidatorMock; - protected function setUp() { - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->paymentMethodManagementMock = $this->createMock( - \Magento\Quote\Api\PaymentMethodManagementInterface::class - ); + $this->objectManager = new ObjectManager($this); + $this->paymentMethodManagementMock = $this->createMock(PaymentMethodManagementInterface::class); $this->paymentDetailsFactoryMock = $this->createPartialMock( - \Magento\Checkout\Model\PaymentDetailsFactory::class, + PaymentDetailsFactory::class, ['create'] ); - $this->cartTotalsRepositoryMock = $this->createMock(\Magento\Quote\Api\CartTotalRepositoryInterface::class); - $this->quoteRepositoryMock = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class); + $this->cartTotalsRepositoryMock = $this->createMock(CartTotalRepositoryInterface::class); + $this->quoteRepositoryMock = $this->createMock(CartRepositoryInterface::class); $this->shippingAddressMock = $this->createPartialMock( - \Magento\Quote\Model\Quote\Address::class, + Address::class, [ 'getSaveInAddressBook', 'getSameAsBilling', @@ -120,7 +155,7 @@ protected function setUp() ); $this->quoteMock = $this->createPartialMock( - \Magento\Quote\Model\Quote::class, + Quote::class, [ 'isVirtual', 'getItemsCount', @@ -134,24 +169,22 @@ protected function setUp() 'getExtensionAttributes', 'setExtensionAttributes', 'setBillingAddress' - ], - [], - '', - false + ] ); - $this->shippingAssignmentFactoryMock = - $this->createPartialMock(\Magento\Quote\Model\ShippingAssignmentFactory::class, ['create']); - $this->cartExtensionFactoryMock = - $this->createPartialMock(\Magento\Quote\Api\Data\CartExtensionFactory::class, ['create']); - $this->shippingFactoryMock = - $this->createPartialMock(\Magento\Quote\Model\ShippingFactory::class, ['create']); - $this->addressValidatorMock = $this->createMock( - \Magento\Quote\Model\QuoteAddressValidator::class + $this->shippingAssignmentFactoryMock = $this->createPartialMock( + ShippingAssignmentFactory::class, + ['create'] ); + $this->cartExtensionFactoryMock = $this->createPartialMock( + CartExtensionFactory::class, + ['create'] + ); + $this->shippingFactoryMock = $this->createPartialMock(ShippingFactory::class, ['create']); + $this->addressValidatorMock = $this->createMock(QuoteAddressValidator::class); $this->model = $this->objectManager->getObject( - \Magento\Checkout\Model\ShippingInformationManagement::class, + ShippingInformationManagement::class, [ 'paymentMethodManagement' => $this->paymentMethodManagementMock, 'paymentDetailsFactory' => $this->paymentDetailsFactoryMock, @@ -166,59 +199,80 @@ protected function setUp() } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The shipping method can't be set for an empty cart. Add an item to cart and try again. + * Save address with `InputException` + * + * @return void */ - public function testSaveAddressInformationIfCartIsEmpty() + public function testSaveAddressInformationIfCartIsEmpty(): void { - $cartId = 100; - $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $cartId = self::STUB_CART_ID; + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(0); + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(0); $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') ->with($cartId) ->willReturn($this->quoteMock); + $this->expectException(InputException::class); + $this->expectExceptionMessage( + 'The shipping method can\'t be set for an empty cart. Add an item to cart and try again.' + ); $this->model->saveAddressInformation($cartId, $addressInformationMock); } /** + * Sets shipping assignments + * * @param string $shippingMethod + * @return void */ - private function setShippingAssignmentsMocks($shippingMethod) + private function setShippingAssignmentsMocks($shippingMethod): void { - $this->quoteMock->expects($this->once())->method('getExtensionAttributes')->willReturn(null); - $this->shippingAddressMock->expects($this->once())->method('setLimitCarrier'); + $this->quoteMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn(null); + $this->shippingAddressMock->expects($this->once()) + ->method('setLimitCarrier'); $this->cartExtensionMock = $this->createPartialMock( - \Magento\Quote\Api\Data\CartExtension::class, + CartExtension::class, ['getShippingAssignments', 'setShippingAssignments'] ); $this->cartExtensionFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->cartExtensionMock); - $this->cartExtensionMock->expects($this->once())->method('getShippingAssignments')->willReturn(null); + $this->cartExtensionMock->expects($this->once()) + ->method('getShippingAssignments') + ->willReturn(null); - $this->shippingAssignmentMock = $this->createMock( - \Magento\Quote\Model\ShippingAssignment::class - ); + $this->shippingAssignmentMock = $this->createMock(ShippingAssignment::class); $this->shippingAssignmentFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->shippingAssignmentMock); - $this->shippingAssignmentMock->expects($this->once())->method('getShipping')->willReturn(null); + $this->shippingAssignmentMock->expects($this->once()) + ->method('getShipping') + ->willReturn(null); - $this->shippingMock = $this->createMock(\Magento\Quote\Model\Shipping::class); - $this->shippingFactoryMock->expects($this->once())->method('create')->willReturn($this->shippingMock); + $shippingMock = $this->createMock(Shipping::class); + $this->shippingFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($shippingMock); - $this->shippingMock->expects($this->once()) + $shippingMock->expects($this->once()) ->method('setAddress') ->with($this->shippingAddressMock) ->willReturnSelf(); - $this->shippingMock->expects($this->once())->method('setMethod')->with($shippingMethod)->willReturnSelf(); + $shippingMock->expects($this->once()) + ->method('setMethod') + ->with($shippingMethod) + ->willReturnSelf(); $this->shippingAssignmentMock->expects($this->once()) ->method('setShipping') - ->with($this->shippingMock) + ->with($shippingMock) ->willReturnSelf(); $this->cartExtensionMock->expects($this->once()) @@ -233,38 +287,116 @@ private function setShippingAssignmentsMocks($shippingMethod) } /** - * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage The shipping address is missing. Set the address and try again. + * Save address with `StateException` + * + * @return void */ - public function testSaveAddressInformationIfShippingAddressNotSet() + public function testSaveAddressInformationIfShippingAddressNotSet(): void { - $cartId = 100; - $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $cartId = self::STUB_CART_ID; + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); $addressInformationMock->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddressMock); - $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn(null); + $this->shippingAddressMock->expects($this->once()) + ->method('getCountryId') + ->willReturn(null); + + $this->quoteRepositoryMock->expects($this->once()) + ->method('getActive') + ->with($cartId) + ->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(self::STUB_ITEMS_COUNT); + + $this->expectException(StateException::class); + $this->expectExceptionMessage('The shipping address is missing. Set the address and try again.'); + $this->model->saveAddressInformation($cartId, $addressInformationMock); + } + + /** + * Save address with `LocalizedException` + * + * @return void + */ + public function testSaveAddressInformationWithLocalizedException(): void + { + $cartId = self::STUB_CART_ID; + $carrierCode = self::STUB_CARRIER_CODE; + $shippingMethod = self::STUB_SHIPPING_METHOD; + $errorMessage = self::STUB_ERROR_MESSAGE; + $exception = new LocalizedException(__($errorMessage)); + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); + + $this->addressValidatorMock->expects($this->exactly(2)) + ->method('validateForCart'); $this->quoteRepositoryMock->expects($this->once()) ->method('getActive') ->with($cartId) ->willReturn($this->quoteMock); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(100); + $addressInformationMock->expects($this->once()) + ->method('getShippingAddress') + ->willReturn($this->shippingAddressMock); + $addressInformationMock->expects($this->once()) + ->method('getShippingCarrierCode') + ->willReturn($carrierCode); + $addressInformationMock->expects($this->once()) + ->method('getShippingMethodCode') + ->willReturn($shippingMethod); + + $billingAddress = $this->createMock(AddressInterface::class); + $addressInformationMock->expects($this->once()) + ->method('getBillingAddress') + ->willReturn($billingAddress); + + $this->shippingAddressMock->expects($this->once()) + ->method('getCountryId') + ->willReturn('USA'); + + $this->setShippingAssignmentsMocks($carrierCode . '_' . $shippingMethod); + + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(self::STUB_ITEMS_COUNT); + $this->quoteMock->expects($this->once()) + ->method('setIsMultiShipping') + ->with(false) + ->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('setBillingAddress') + ->with($billingAddress) + ->willReturnSelf(); + + $this->quoteRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->quoteMock) + ->willThrowException($exception); + + $this->expectException(LocalizedException::class); + $this->expectExceptionMessage( + 'The shipping information was unable to be saved. Error: "' . $errorMessage . '"' + ); $this->model->saveAddressInformation($cartId, $addressInformationMock); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The shipping information was unable to be saved. Verify the input data and try again. + * Save address with `InputException` + * + * @return void */ - public function testSaveAddressInformationIfCanNotSaveQuote() + public function testSaveAddressInformationIfCanNotSaveQuote(): void { - $cartId = 100; - $carrierCode = 'carrier_code'; - $shippingMethod = 'shipping_method'; - $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $cartId = self::STUB_CART_ID; + $carrierCode = self::STUB_CARRIER_CODE; + $shippingMethod = self::STUB_SHIPPING_METHOD; + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); $this->addressValidatorMock->expects($this->exactly(2)) ->method('validateForCart'); @@ -277,38 +409,59 @@ public function testSaveAddressInformationIfCanNotSaveQuote() $addressInformationMock->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddressMock); - $addressInformationMock->expects($this->once())->method('getShippingCarrierCode')->willReturn($carrierCode); - $addressInformationMock->expects($this->once())->method('getShippingMethodCode')->willReturn($shippingMethod); + $addressInformationMock->expects($this->once()) + ->method('getShippingCarrierCode') + ->willReturn($carrierCode); + $addressInformationMock->expects($this->once()) + ->method('getShippingMethodCode') + ->willReturn($shippingMethod); - $billingAddress = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $addressInformationMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddress); + $billingAddress = $this->createMock(AddressInterface::class); + $addressInformationMock->expects($this->once()) + ->method('getBillingAddress') + ->willReturn($billingAddress); - $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn('USA'); + $this->shippingAddressMock->expects($this->once()) + ->method('getCountryId') + ->willReturn('USA'); $this->setShippingAssignmentsMocks($carrierCode . '_' . $shippingMethod); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(100); - $this->quoteMock->expects($this->once())->method('setIsMultiShipping')->with(false)->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('setBillingAddress')->with($billingAddress)->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(self::STUB_ITEMS_COUNT); + $this->quoteMock->expects($this->once()) + ->method('setIsMultiShipping') + ->with(false)->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('setBillingAddress') + ->with($billingAddress) + ->willReturnSelf(); $this->quoteRepositoryMock->expects($this->once()) ->method('save') ->with($this->quoteMock) ->willThrowException(new \Exception()); + $this->expectException(InputException::class); + $this->expectExceptionMessage( + 'The shipping information was unable to be saved. Verify the input data and try again.' + ); $this->model->saveAddressInformation($cartId, $addressInformationMock); } /** - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Carrier with such method not found: carrier_code, shipping_method + * Save address with `NoSuchEntityException` + * + * @return void */ - public function testSaveAddressInformationIfCarrierCodeIsInvalid() + public function testSaveAddressInformationIfCarrierCodeIsInvalid(): void { - $cartId = 100; - $carrierCode = 'carrier_code'; - $shippingMethod = 'shipping_method'; - $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $cartId = self::STUB_CART_ID; + $carrierCode = self::STUB_CARRIER_CODE; + $shippingMethod = self::STUB_SHIPPING_METHOD; + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); $this->addressValidatorMock->expects($this->exactly(2)) ->method('validateForCart'); @@ -320,39 +473,70 @@ public function testSaveAddressInformationIfCarrierCodeIsInvalid() $addressInformationMock->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddressMock); - $addressInformationMock->expects($this->once())->method('getShippingCarrierCode')->willReturn($carrierCode); - $addressInformationMock->expects($this->once())->method('getShippingMethodCode')->willReturn($shippingMethod); + $addressInformationMock->expects($this->once()) + ->method('getShippingCarrierCode') + ->willReturn($carrierCode); + $addressInformationMock->expects($this->once()) + ->method('getShippingMethodCode') + ->willReturn($shippingMethod); - $billingAddress = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $addressInformationMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddress); - $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn('USA'); + $billingAddress = $this->createMock(AddressInterface::class); + $addressInformationMock->expects($this->once()) + ->method('getBillingAddress') + ->willReturn($billingAddress); + $this->shippingAddressMock->expects($this->once()) + ->method('getCountryId') + ->willReturn('USA'); $this->setShippingAssignmentsMocks($carrierCode . '_' . $shippingMethod); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(100); - $this->quoteMock->expects($this->once())->method('setIsMultiShipping')->with(false)->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('setBillingAddress')->with($billingAddress)->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($this->shippingAddressMock); + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(self::STUB_ITEMS_COUNT); + $this->quoteMock->expects($this->once()) + ->method('setIsMultiShipping') + ->with(false) + ->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('setBillingAddress') + ->with($billingAddress) + ->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('getShippingAddress') + ->willReturn($this->shippingAddressMock); $this->quoteRepositoryMock->expects($this->once()) ->method('save') ->with($this->quoteMock); - $this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod); + $this->shippingAddressMock->expects($this->once()) + ->method('getShippingMethod') + ->willReturn($shippingMethod); $this->shippingAddressMock->expects($this->once()) ->method('getShippingRateByCode') ->with($shippingMethod) ->willReturn(false); + $this->expectException(NoSuchEntityException::class); + $this->expectExceptionMessage( + 'Carrier with such method not found: ' . self::STUB_CARRIER_CODE . ', ' . self::STUB_SHIPPING_METHOD + ); + $this->model->saveAddressInformation($cartId, $addressInformationMock); } - public function testSaveAddressInformation() + /** + * Save address info test + * + * @return void + */ + public function testSaveAddressInformation(): void { - $cartId = 100; - $carrierCode = 'carrier_code'; - $shippingMethod = 'shipping_method'; - $addressInformationMock = $this->createMock(\Magento\Checkout\Api\Data\ShippingInformationInterface::class); + $cartId = self::STUB_CART_ID; + $carrierCode = self::STUB_CARRIER_CODE; + $shippingMethod = self::STUB_SHIPPING_METHOD; + /** @var ShippingInformationInterface|MockObject $addressInformationMock */ + $addressInformationMock = $this->createMock(ShippingInformationInterface::class); $this->addressValidatorMock->expects($this->exactly(2)) ->method('validateForCart'); @@ -364,40 +548,62 @@ public function testSaveAddressInformation() $addressInformationMock->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddressMock); - $addressInformationMock->expects($this->once())->method('getShippingCarrierCode')->willReturn($carrierCode); - $addressInformationMock->expects($this->once())->method('getShippingMethodCode')->willReturn($shippingMethod); + $addressInformationMock->expects($this->once()) + ->method('getShippingCarrierCode') + ->willReturn($carrierCode); + $addressInformationMock->expects($this->once()) + ->method('getShippingMethodCode') + ->willReturn($shippingMethod); - $billingAddress = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class); - $addressInformationMock->expects($this->once())->method('getBillingAddress')->willReturn($billingAddress); - $this->shippingAddressMock->expects($this->once())->method('getCountryId')->willReturn('USA'); + $billingAddress = $this->createMock(AddressInterface::class); + $addressInformationMock->expects($this->once()) + ->method('getBillingAddress') + ->willReturn($billingAddress); + $this->shippingAddressMock->expects($this->once()) + ->method('getCountryId') + ->willReturn('USA'); $this->setShippingAssignmentsMocks($carrierCode . '_' . $shippingMethod); - $this->quoteMock->expects($this->once())->method('getItemsCount')->willReturn(100); - $this->quoteMock->expects($this->once())->method('setIsMultiShipping')->with(false)->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('setBillingAddress')->with($billingAddress)->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($this->shippingAddressMock); + $this->quoteMock->expects($this->once()) + ->method('getItemsCount') + ->willReturn(self::STUB_ITEMS_COUNT); + $this->quoteMock->expects($this->once()) + ->method('setIsMultiShipping') + ->with(false) + ->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('setBillingAddress') + ->with($billingAddress) + ->willReturnSelf(); + $this->quoteMock->expects($this->once()) + ->method('getShippingAddress') + ->willReturn($this->shippingAddressMock); $this->quoteRepositoryMock->expects($this->once()) ->method('save') ->with($this->quoteMock); - $this->shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod); + $this->shippingAddressMock->expects($this->once()) + ->method('getShippingMethod') + ->willReturn($shippingMethod); $this->shippingAddressMock->expects($this->once()) ->method('getShippingRateByCode') ->with($shippingMethod) ->willReturn('rates'); - $paymentDetailsMock = $this->createMock(\Magento\Checkout\Api\Data\PaymentDetailsInterface::class); - $this->paymentDetailsFactoryMock->expects($this->once())->method('create')->willReturn($paymentDetailsMock); + $paymentDetailsMock = $this->createMock(PaymentDetailsInterface::class); + $this->paymentDetailsFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($paymentDetailsMock); - $paymentMethodMock = $this->createMock(\Magento\Quote\Api\Data\PaymentMethodInterface::class); + $paymentMethodMock = $this->createMock(PaymentMethodInterface::class); $this->paymentMethodManagementMock->expects($this->once()) ->method('getList') ->with($cartId) ->willReturn([$paymentMethodMock]); - $cartTotalsMock = $this->createMock(\Magento\Quote\Api\Data\TotalsInterface::class); + $cartTotalsMock = $this->createMock(TotalsInterface::class); $this->cartTotalsRepositoryMock->expects($this->once()) ->method('get') ->with($cartId) @@ -407,7 +613,9 @@ public function testSaveAddressInformation() ->method('setPaymentMethods') ->with([$paymentMethodMock]) ->willReturnSelf(); - $paymentDetailsMock->expects($this->once())->method('setTotals')->with()->willReturnSelf($cartTotalsMock); + $paymentDetailsMock->expects($this->once()) + ->method('setTotals') + ->willReturn($cartTotalsMock); $this->assertEquals( $paymentDetailsMock, diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml index 69d2523d88dfb..4b5d1033408e4 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_cart_index.xml @@ -189,6 +189,7 @@ <block class="Magento\Checkout\Block\Cart\Crosssell" name="checkout.cart.crosssell" template="Magento_Catalog::product/list/items.phtml" after="-" ifconfig="checkout/cart/crosssell_enabled"> <arguments> <argument name="type" xsi:type="string">crosssell</argument> + <argument name="view_model" xsi:type="object">Magento\Catalog\ViewModel\Product\Listing\PreparePostData</argument> </arguments> <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="crosssell.product.addto" as="addto"> <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare" diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml index fed0c951eff9f..c33b784fcd20c 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_index_index.xml @@ -222,9 +222,6 @@ <item name="min_text_length" xsi:type="number">0</item> </item> </item> - <item name="country_id" xsi:type="array"> - <item name="sortOrder" xsi:type="string">115</item> - </item> <item name="telephone" xsi:type="array"> <item name="config" xsi:type="array"> <item name="tooltip" xsi:type="array"> diff --git a/app/code/Magento/Checkout/view/frontend/requirejs-config.js b/app/code/Magento/Checkout/view/frontend/requirejs-config.js index 1f552b779539c..602a1227644c0 100644 --- a/app/code/Magento/Checkout/view/frontend/requirejs-config.js +++ b/app/code/Magento/Checkout/view/frontend/requirejs-config.js @@ -12,7 +12,8 @@ var config = { sidebar: 'Magento_Checkout/js/sidebar', checkoutLoader: 'Magento_Checkout/js/checkout-loader', checkoutData: 'Magento_Checkout/js/checkout-data', - proceedToCheckout: 'Magento_Checkout/js/proceed-to-checkout' + proceedToCheckout: 'Magento_Checkout/js/proceed-to-checkout', + catalogAddToCart: 'Magento_Catalog/js/catalog-add-to-cart' } } }; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js index 086859fa8021d..1f14ab444e0c1 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js @@ -18,7 +18,7 @@ define([ if (quote.shippingAddress() && billingAddress.getCacheKey() == //eslint-disable-line eqeqeq quote.shippingAddress().getCacheKey() ) { - address = $.extend({}, billingAddress); + address = $.extend(true, {}, billingAddress); address.saveInAddressBook = null; } else { address = billingAddress; diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveHtmlTermEntityTest.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveHtmlTermEntityTest.xml index dc329ae63ba21..1e87d73c26205 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveHtmlTermEntityTest.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveHtmlTermEntityTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteTermActionGroup" stepKey="deleteTerm"> <argument name="term" value="activeHtmlTerm"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateNewTermActionGroup" stepKey="createTerm"> diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveTextTermEntityTest.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveTextTermEntityTest.xml index a7baa061750c5..2db3377e0e89e 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveTextTermEntityTest.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateActiveTextTermEntityTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteTermActionGroup" stepKey="deleteTerm"> <argument name="term" value="activeTextTerm"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateNewTermActionGroup" stepKey="createTerm"> diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateDisabledTextTermEntityTest.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateDisabledTextTermEntityTest.xml index d5f35fc79fbed..df666ecab817b 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateDisabledTextTermEntityTest.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateDisabledTextTermEntityTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="DeleteTermActionGroup" stepKey="deleteTerm"> <argument name="term" value="disabledTextTerm"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateNewTermActionGroup" stepKey="createTerm"> diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateEnabledTextTermOnMultishippingEntityTest.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateEnabledTextTermOnMultishippingEntityTest.xml index 462b13ae386c4..fec2365431862 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateEnabledTextTermOnMultishippingEntityTest.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminCreateEnabledTextTermOnMultishippingEntityTest.xml @@ -36,7 +36,7 @@ <actionGroup ref="DeleteTermActionGroup" stepKey="deleteTerm"> <argument name="term" value="activeTextTerm"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateNewTermActionGroup" stepKey="createTerm"> diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminStoresTermsAndConditionsNavigateMenuTest.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminStoresTermsAndConditionsNavigateMenuTest.xml index d2d4cb9138bd5..7ffabcfa51215 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminStoresTermsAndConditionsNavigateMenuTest.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/Test/AdminStoresTermsAndConditionsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresTermsAndConditionsPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php index 97d0b35a2354f..a3370b2666264 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Directive.php @@ -21,6 +21,7 @@ use Magento\Framework\Controller\Result\RawFactory; use Magento\Backend\App\Action\Context; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Filesystem\Driver\File; /** * Process template text for wysiwyg editor. @@ -67,6 +68,11 @@ class Directive extends Action implements HttpGetActionInterface */ private $filter; + /** + * @var File + */ + private $file; + /** * Constructor * @@ -77,6 +83,7 @@ class Directive extends Action implements HttpGetActionInterface * @param LoggerInterface|null $logger * @param Config|null $config * @param Filter|null $filter + * @param File|null $file */ public function __construct( Context $context, @@ -85,7 +92,8 @@ public function __construct( AdapterFactory $adapterFactory = null, LoggerInterface $logger = null, Config $config = null, - Filter $filter = null + Filter $filter = null, + File $file = null ) { parent::__construct($context); $this->urlDecoder = $urlDecoder; @@ -94,6 +102,7 @@ public function __construct( $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class); $this->config = $config ?: ObjectManager::getInstance()->get(Config::class); $this->filter = $filter ?: ObjectManager::getInstance()->get(Filter::class); + $this->file = $file ?: ObjectManager::getInstance()->get(File::class); } /** @@ -127,6 +136,15 @@ public function execute() $this->logger->warning($e); } } + $mimeType = $image->getMimeType(); + unset($image); + // To avoid issues with PNG images with alpha blending we return raw file + // after validation as an image source instead of generating the new PNG image + // with image adapter + $content = $this->file->fileGetContents($imagePath); + $resultRaw->setHeader('Content-Type', $mimeType); + $resultRaw->setContents($content); + return $resultRaw; } } diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block.php b/app/code/Magento/Cms/Model/ResourceModel/Block.php index 30e817713755c..1324b9bd127e9 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Block.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Block.php @@ -185,13 +185,9 @@ public function getIsUniqueBlockToStores(AbstractModel $object) $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class); $linkField = $entityMetadata->getLinkField(); - $stores = (array)$object->getData('store_id'); - $isDefaultStore = $this->_storeManager->isSingleStoreMode() - || array_search(Store::DEFAULT_STORE_ID, $stores) !== false; - - if (!$isDefaultStore) { - $stores[] = Store::DEFAULT_STORE_ID; - } + $stores = $this->_storeManager->isSingleStoreMode() + ? [Store::DEFAULT_STORE_ID] + : (array)$object->getData('store_id'); $select = $this->getConnection()->select() ->from(['cb' => $this->getMainTable()]) @@ -200,11 +196,8 @@ public function getIsUniqueBlockToStores(AbstractModel $object) 'cb.' . $linkField . ' = cbs.' . $linkField, [] ) - ->where('cb.identifier = ? ', $object->getData('identifier')); - - if (!$isDefaultStore) { - $select->where('cbs.store_id IN (?)', $stores); - } + ->where('cb.identifier = ? ', $object->getData('identifier')) + ->where('cbs.store_id IN (?)', $stores); if ($object->getId()) { $select->where('cb.' . $entityMetadata->getIdentifierField() . ' <> ?', $object->getId()); diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml new file mode 100644 index 0000000000000..c221dd62cd7f6 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AdminClickInsertWidgetActionGroup"> + <annotations> + <description>Click "Insert Widget" button in the opened widget popup</description> + </annotations> + + <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetButton"/> + <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForWidgetPopupDisappear"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml new file mode 100644 index 0000000000000..685385382027b --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml @@ -0,0 +1,25 @@ +<?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="AdminFillCmsBlockFormActionGroup"> + <annotations> + <description>Fills in the Block Title, Identifier with marginal space, Store View and Content. PLEASE NOTE: The values are passed through arguments in test.</description> + </annotations> + <arguments> + <argument name="cmsBlockDataTitle" type="string" /> + <argument name="cmsBlockDataIdentifier" type="string" /> + <argument name="cmsBlockDataContent" type="string" /> + </arguments> + <fillField selector="{{BlockNewPageBasicFieldsSection.blockTitle}}" userInput="{{cmsBlockDataTitle}}" stepKey="fillFieldTitle1"/> + <fillField selector="{{BlockNewPageBasicFieldsSection.identifier}}" userInput="{{cmsBlockDataIdentifier}}" stepKey="fillFieldIdentifier"/> + <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="All Store View" stepKey="selectAllStoreView"/> + <fillField selector="{{BlockContentSection.TextArea}}" userInput="{{cmsBlockDataContent}}" stepKey="fillContentField"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml new file mode 100644 index 0000000000000..734d8d98722b2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml @@ -0,0 +1,25 @@ +<?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="AdminInsertWidgetToCmsPageContentActionGroup"> + <annotations> + <description>Insert widget to CMS Page content field. You are on CMS edit page, content tab is expanded.</description> + </annotations> + + <arguments> + <argument name="widgetType" type="string" defaultValue="CMS Page Link"/> + </arguments> + <waitForElementVisible selector="{{CmsNewPagePageActionsSection.insertWidget}}" stepKey="waitForInsertWidgetElementVisible"/> + <click selector="{{CmsNewPagePageActionsSection.insertWidget}}" stepKey="clickOnInsertWidgetButton"/> + <waitForPageLoad stepKey="waitForPageLoadAfterClickOnInsertWidgetButton"/> + <waitForElementVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForInsertWidgetTitle"/> + <selectOption selector="{{WidgetSection.WidgetType}}" userInput="{{widgetType}}" stepKey="selectWidgetType"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndDuplicateCMSPageWithSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndDuplicateCMSPageWithSplitButtonActionGroup.xml new file mode 100644 index 0000000000000..43c0fc9ff3a45 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndDuplicateCMSPageWithSplitButtonActionGroup.xml @@ -0,0 +1,23 @@ +<?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="AdminSaveAndDuplicateCMSPageWithSplitButtonActionGroup"> + <annotations> + <description>Clicks on the Save and Duplicate button.</description> + </annotations> + + <waitForElementVisible selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="waitForExpandSplitButtonToBeVisible"/> + <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> + <click selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> + <waitForPageLoad stepKey="waitForPageLoadAfterClickingSaveAndDuplicate"/> + <see userInput="You saved the page." stepKey="seeSavedPageMsgOnForm"/> + <see userInput="You duplicated the page." stepKey="seeDuplicatedPageMsg"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertAdminCmsPageSaveSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertAdminCmsPageSaveSplitButtonActionGroup.xml new file mode 100644 index 0000000000000..6ea87aeae5998 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertAdminCmsPageSaveSplitButtonActionGroup.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="AssertAdminCmsPageSaveSplitButtonActionGroup"> + <annotations> + <description>Verify Save and Duplicate and Save and Close button.</description> + </annotations> + + <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPageCreationForm"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> + <see selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> + <see selector="{{CmsNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml index 95ce3c499b6b8..44e29f7e2fe55 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndCloseCMSBlockWithSplitButtonActionGroup.xml @@ -17,6 +17,7 @@ <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitButton"/> <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveBlock"/> <waitForPageLoad stepKey="waitForPageLoadAfterClickingSave"/> - <see userInput="You saved the block." stepKey="assertSaveBlockSuccessMessage"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppear"/> + <see userInput="You saved the block." selector="{{AdminMessagesSection.success}}" stepKey="assertSaveBlockSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml index fee2f984c42d2..bc30098cb43c7 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml @@ -17,6 +17,7 @@ <waitForPageLoad stepKey="waitForPageLoad1"/> <!--Verify Save&Duplicate button and Save&Close button--> <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> + <waitForElementVisible selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" stepKey="waitForButtonMenuOpened"/> <see selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> <see selector="{{BlockNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> </actionGroup> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToCMSPageTinyMCE3Test.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToCMSPageTinyMCE3Test.xml index 69f9d24699db0..f54547015eb9c 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToCMSPageTinyMCE3Test.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToCMSPageTinyMCE3Test.xml @@ -28,7 +28,7 @@ <!-- Switch WYSIWYG editor to TinyMCE4--> <comment userInput="Reset editor as TinyMCE4" stepKey="chooseTinyMCE4AsEditor"/> <magentoCLI command="config:set cms/wysiwyg/editor mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter" stepKey="enableTinyMCE4"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{CmsNewPagePage.url}}" stepKey="navigateToPage2"/> <waitForPageLoad stepKey="wait5"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGBlockTest.xml index 64b775c6cbef9..e22f6e085a32b 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGBlockTest.xml @@ -20,7 +20,7 @@ <before> <createData entity="_defaultCmsPage" stepKey="createCMSPage" /> <createData entity="_defaultBlock" stepKey="createPreReqBlock" /> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -63,7 +63,7 @@ <deleteData createDataKey="createPreReqBlock" stepKey="deletePreReqBlock" /> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGCMSTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGCMSTest.xml index 201a84ecb3c65..51afa7b59d366 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGCMSTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddImageToWYSIWYGCMSTest.xml @@ -19,7 +19,7 @@ </annotations> <before> <createData entity="_defaultCmsPage" stepKey="createCMSPage" /> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -58,7 +58,7 @@ <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYGFirst"/> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml index cc7f59c7a9478..32bd75d373115 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml @@ -20,7 +20,7 @@ <before> <createData entity="_defaultCmsPage" stepKey="createCMSPage" /> <createData entity="_defaultBlock" stepKey="createPreReqBlock" /> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -143,7 +143,7 @@ <deleteData createDataKey="createPreReqBlock" stepKey="deletePreReqBlock" /> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml index 92164f34f5a83..55c01f3818a19 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml @@ -17,7 +17,7 @@ <testCaseId value="MAGETWO-83504"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -95,7 +95,7 @@ <dontSee userInput="{{customVariable.html}}" stepKey="dontSeeCustomVariableName" /> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml index 24440a6164e84..e5aecd0f3da81 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml @@ -20,7 +20,7 @@ <before> <createData entity="_defaultCmsPage" stepKey="createCMSPage" /> <createData entity="_defaultBlock" stepKey="createPreReqBlock" /> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -81,7 +81,7 @@ <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage" /> <deleteData createDataKey="createPreReqBlock" stepKey="deletePreReqBlock" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml index 53ed63c89bfb6..5f9bfaf47a157 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml @@ -19,7 +19,7 @@ <testCaseId value="MAGETWO-83781"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -67,7 +67,7 @@ <see userInput="Home page" stepKey="seeHomepageWidget" /> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml index c199601231a13..81826eeab5e10 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml @@ -20,7 +20,7 @@ </annotations> <before> <createData entity="_defaultBlock" stepKey="createPreReqBlock" /> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -69,7 +69,7 @@ <after> <deleteData createDataKey="createPreReqBlock" stepKey="deletePreReqBlock" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml index 0237d3704f7c1..5d745c625ac10 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml @@ -19,7 +19,7 @@ </annotations> <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> <actionGroup ref="ConfigAdminAccountSharingActionGroup" stepKey="allowAdminShareAccount"/> @@ -77,7 +77,7 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCatalog" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="enableGenerateUrlRewrite"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml index 4e7ecd48a6af4..940c1979710e1 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml @@ -23,7 +23,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -84,7 +84,7 @@ <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="enableGenerateUrlRewrite"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml index 2cd41eb9d9f7b..f849c31948c3c 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml @@ -25,7 +25,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct2"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -100,7 +100,7 @@ <deleteData createDataKey="createPreReqProduct1" stepKey="deletePreReqProduct1" /> <deleteData createDataKey="createPreReqProduct2" stepKey="deletePreReqProduct2" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml index 803a3b692dbe2..f4f1da8763fbb 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml @@ -24,7 +24,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -83,7 +83,7 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCatalog" /> <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml index 2c3b060d3bc15..d9c080e034dd2 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml @@ -23,7 +23,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -73,7 +73,7 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCatalog" /> <deleteData createDataKey="createPreReqProduct" stepKey="deletePreReqProduct" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml index a5f43b090e9d6..3c6d70dc53418 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to New CMS Page page--> <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml index d63952f7eb6c8..036efab75f963 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to New CMS Page page--> <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml index d2124b5d83be6..1b3a7e74af08f 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml @@ -26,7 +26,7 @@ </before> <after> <magentoCLI command="config:set {{StorefrontSingleStoreModeDisabledConfigData.path}} {{StorefrontSingleStoreModeDisabledConfigData.value}}" stepKey="disableSingleStoreMode" /> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to New CMS Page page--> <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml index d33d7484f7770..a097a6d11403e 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to New CMS Page page--> <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml index 1600a0d9d8d0f..9c2f1abc4d522 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to New CMS Page page--> <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml index 7cc0719dcbeb2..4c9ef31b0d202 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -10,6 +10,7 @@ <test name="AdminCmsPageMassActionTest"> <annotations> <features value="CmsPage"/> + <stories value="Create CMS Page"/> <title value="Create two CMS Pages and perform mass disable action"/> <description value="Admin should be able to perform mass actions to CMS pages"/> <stories value="Admin Grid Mass Action" /> @@ -27,7 +28,7 @@ <after> <deleteData createDataKey="firstCMSPage" stepKey="deleteFirstCMSPage" /> <deleteData createDataKey="secondCMSPage" stepKey="deleteSecondCMSPage" /> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to Grid page--> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml new file mode 100644 index 0000000000000..99990595fca95 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml @@ -0,0 +1,44 @@ +<?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="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> + <annotations> + <features value="Cms"/> + <stories value="Default layout configuration MAGETWO-88793"/> + <title value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> + <description value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-89025"/> + <group value="Cms"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick stepKey="expandDefaultLayouts" selector="{{WebSection.DefaultLayoutsTab}}" dependentSelector="{{WebSection.CheckIfTabExpand}}" visible="true" /> + <waitForElementVisible selector="{{DefaultLayoutsSection.pageLayout}}" stepKey="DefaultProductLayout" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.pageLayout}}" userInput="1 column" stepKey="seeOneColumnSelected" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.productLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected1" /> + <seeOptionIsSelected selector="{{DefaultLayoutsSection.categoryLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected2" /> + <selectOption selector="{{DefaultLayoutsSection.pageLayout}}" userInput="2 columns with right bar" stepKey="selectColumnsWithRightBar"/> + <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> + <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPagePagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <waitForLoadingMaskToDisappear stepKey="wait2" /> + <click selector="{{CmsDesignSection.DesignTab}}" stepKey="clickOnDesignTab"/> + <waitForElementVisible selector="{{CmsDesignSection.LayoutDropdown}}" stepKey="waitForLayoutDropDown" /> + <seeOptionIsSelected selector="{{CmsDesignSection.LayoutDropdown}}" userInput="2 columns with right bar" stepKey="seeColumnsWithRightBar" /> + </test> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminContentBlocksNavigateMenuTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminContentBlocksNavigateMenuTest.xml index 19f501d6aa209..bb15904540be4 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminContentBlocksNavigateMenuTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminContentBlocksNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToContentBlocksPage"> <argument name="menuUiId" value="{{AdminMenuContent.dataUiId}}"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminContentPagesNavigateMenuTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminContentPagesNavigateMenuTest.xml index 323a1de7b9a4e..c7726e7e427ce 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminContentPagesNavigateMenuTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminContentPagesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToContentPagesPage"> <argument name="menuUiId" value="{{AdminMenuContent.dataUiId}}"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index 33d7b06a064e4..eb13bb71b5f6b 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -17,16 +17,16 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-89185"/> <group value="Cms"/> + <group value="WYSIWYGDisabled"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> </before> <after> <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> <argument name="Block" value="_defaultBlock"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Navigate to create cms block page and verify save split button --> <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="verifyCmsBlockSaveButton" /> @@ -42,4 +42,4 @@ <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveAndCloseAction" /> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml new file mode 100644 index 0000000000000..07f033b18ea39 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml @@ -0,0 +1,42 @@ +<?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="AdminCreateCmsBlockWithMarginalSpaceTest"> + <annotations> + <features value="Cms"/> + <stories value="CMS Block Identifier with marginal space"/> + <title value="Admin can not able create a CMS block with marginal space in identifier field"/> + <description value="Admin can not able create a CMS block with marginal space in identifier field"/> + <severity value="CRITICAL"/> + <group value="Cms"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginGetFromGeneralFile"/> + </before> + + <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnBlocksCreationForm"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <!--Verify Save&Duplicate button and Save&Close button--> + <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> + <see selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> + <see selector="{{BlockNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> + <!--Create new CMS Block page with marginal space in identifier field--> + <actionGroup ref="AdminFillCmsBlockFormActionGroup" stepKey="FillOutBlockContent"> + <argument name="cmsBlockDataTitle" value="Default Block" /> + <argument name="cmsBlockDataIdentifier" value=" block " /> + <argument name="cmsBlockDataContent" value="Here is a block test. Yeah!" /> + </actionGroup> + <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> + <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clicksaveAndClose" /> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <see userInput="No marginal white space please" stepKey="seeNoMarginalSpaceMsgOnIdentifierField"/> + </test> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index e6fcbab4de644..b2fca0ff99115 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -17,88 +17,20 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-25580"/> <group value="Cms"/> + <group value="WYSIWYGDisabled"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="AdminNavigateToPageGridActionGroup" stepKey="navigateToCmsPageGrid" /> <actionGroup ref="CreateNewPageWithBasicValues" stepKey="createNewPageWithBasicValues" /> <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveCmsPageButton" /> <actionGroup ref="VerifyCreatedCmsPage" stepKey="verifyCmsPage" /> - </test> - <test name="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> - <annotations> - <features value="Cms"/> - <stories value="Default layout configuration MAGETWO-88793"/> - <title value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> - <description value="Admin should be able to configure the default layout for CMS Page from System Configuration"/> - <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-89025"/> - <group value="Cms"/> - </annotations> - <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <actionGroup ref="RestoreLayoutSetting" stepKey="sampleActionGroup"/> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <amOnPage url="{{WebConfigurationPage.url}}" stepKey="navigateToWebConfigurationPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <conditionalClick stepKey="expandDefaultLayouts" selector="{{WebSection.DefaultLayoutsTab}}" dependentSelector="{{WebSection.CheckIfTabExpand}}" visible="true" /> - <waitForElementVisible selector="{{DefaultLayoutsSection.pageLayout}}" stepKey="DefaultProductLayout" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.pageLayout}}" userInput="1 column" stepKey="seeOneColumnSelected" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.productLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected1" /> - <seeOptionIsSelected selector="{{DefaultLayoutsSection.categoryLayout}}" userInput="No layout updates" stepKey="seeNoLayoutUpdatesSelected2" /> - <selectOption selector="{{DefaultLayoutsSection.pageLayout}}" userInput="2 columns with right bar" stepKey="selectColumnsWithRightBar"/> - <click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" /> - <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPagePagesGrid"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <waitForLoadingMaskToDisappear stepKey="wait2" /> - <click selector="{{CmsDesignSection.DesignTab}}" stepKey="clickOnDesignTab"/> - <waitForElementVisible selector="{{CmsDesignSection.LayoutDropdown}}" stepKey="waitForLayoutDropDown" /> - <seeOptionIsSelected selector="{{CmsDesignSection.LayoutDropdown}}" userInput="2 columns with right bar" stepKey="seeColumnsWithRightBar" /> - </test> - <test name="AdminCreateDuplicatedCmsPageTest"> - <annotations> - <features value="Cms"/> - <stories value="CMS Page Duplication and Reset Removal MAGETWO-87096"/> - <title value="Admin should be able to duplicate a CMS Page"/> - <description value="Admin should be able to duplicate a CMS Page"/> - <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-89184"/> - <group value="Cms"/> - </annotations> - <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - </before> - <after> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <amOnPage url="{{CmsNewPagePage.url}}" stepKey="amOnPageCreationForm"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <!--Verify Save&Duplicate button and Save&Close button--> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn1" /> - <see selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" userInput="Save & Duplicate" stepKey="seeSaveAndDuplicate"/> - <see selector="{{CmsNewPagePageActionsSection.saveAndClose}}" userInput="Save & Close" stepKey="seeSaveAndClose"/> - <!--Create new CMS Page page--> - <actionGroup ref="FillOutCMSPageContent" stepKey="FillOutBlockContent"/> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> - <click selector="{{CmsNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <see userInput="You saved the page." stepKey="seeSavedPageMsgOnForm"/> - <see userInput="You duplicated the page." stepKey="seeDuplicatedPageMsg"/> - <!--Verify duplicated CMS Page--> - <seeElement selector="{{BlockNewPageBasicFieldsSection.isActive('0')}}" stepKey="seeBlockNotEnable" /> - <actionGroup ref="AssertCMSPageContentActionGroup" stepKey="assertContent"/> - <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn3" /> - <click selector="{{CmsNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose"/> - <see userInput="You saved the page." stepKey="seeSavedCMSPageMsgOnGrid"/> - <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> + <actionGroup ref="DeletePageByUrlKeyActionGroup" stepKey="deletePage"> + <argument name="UrlKey" value="{{_defaultCmsPage.identifier}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml new file mode 100644 index 0000000000000..1e2e47de8c17f --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml @@ -0,0 +1,43 @@ +<?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="AdminCreateDuplicatedCmsPageTest"> + <annotations> + <features value="Cms"/> + <stories value="CMS Page Duplication and Reset Removal MAGETWO-87096"/> + <title value="Admin should be able to duplicate a CMS Page"/> + <description value="Admin should be able to duplicate a CMS Page"/> + <severity value="CRITICAL"/> + <testCaseId value="MAGETWO-89184"/> + <group value="Cms"/> + <group value="WYSIWYGDisabled"/> + </annotations> + <before> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> + </before> + <after> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + <!-- Navigate to create a CMS page and Verify Save&Duplicate - Save&Close button --> + <actionGroup ref="AssertAdminCmsPageSaveSplitButtonActionGroup" stepKey="verifyCmsPageSaveButton" /> + <!-- Filled out Content --> + <actionGroup ref="FillOutCMSPageContent" stepKey="FillOutPageContent"/> + <!-- Click save and duplicate action --> + <actionGroup ref="AdminSaveAndDuplicateCMSPageWithSplitButtonActionGroup" stepKey="clickSaveAndDuplicateButton"/> + <!--Verify duplicated CMS Page--> + <seeElement selector="{{BlockNewPageBasicFieldsSection.isActive('0')}}" stepKey="seeBlockNotEnable" /> + <actionGroup ref="AssertCMSPageContentActionGroup" stepKey="assertContent"/> + <!-- Click Save Button --> + <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveCmsPageButton"/> + <actionGroup ref="DeletePageByUrlKeyActionGroup" stepKey="deleteCMSPage"> + <argument name="UrlKey" value="{{_duplicatedCMSPage.identifier}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminMediaGalleryPopupUploadImagesWithoutErrorTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminMediaGalleryPopupUploadImagesWithoutErrorTest.xml index ff389a6ce2965..58803533efaf2 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminMediaGalleryPopupUploadImagesWithoutErrorTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminMediaGalleryPopupUploadImagesWithoutErrorTest.xml @@ -26,14 +26,14 @@ <!--Create block--> <comment userInput="Create block" stepKey="commentCreateBlock"/> <createData entity="Sales25offBlock" stepKey="createBlock"/> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> </before> <after> <!--Disable WYSIWYG options--> <comment userInput="Disable WYSIWYG options" stepKey="commentDisableWYSIWYG"/> <magentoCLI command="config:set cms/wysiwyg/enabled disabled" stepKey="disableWYSIWYG"/> <deleteData createDataKey="createBlock" stepKey="deleteBlock" /> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open created block page and add image--> <comment userInput="Open create block page and add image" stepKey="commentOpenBlockPage"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml index 8c89c47ab5077..e2800c2ac3094 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml @@ -16,21 +16,25 @@ <description value="Admin should be able to create a CMS block using save and close"/> <severity value="CRITICAL"/> <group value="Cms"/> + <group value="WYSIWYGDisabled"/> </annotations> + <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> </before> + <after> <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> <argument name="Block" value="_defaultBlock"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> + <!-- Navigate to create cms block page and verify save split button --> - <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="verifyCmsBlockSaveSplitButton" /> + <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="assertCmsBlockSaveSplitButton"/> <!--Create new CMS Block page--> - <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> + <actionGroup ref="FillOutBlockContent" stepKey="fillOutBlockContent"/> <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveCmsBlockContent" /> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml index afcf5e3764ef7..58adae02298b7 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="product1" stepKey="deleteProduct1"/> <deleteData createDataKey="product2" stepKey="deleteProduct2"/> <deleteData createDataKey="createCMSPage" stepKey="deletePreReqCMSPage"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage1"> <argument name="CMSPage" value="$$createCMSPage$$"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml index e6ab1c130606b..385616dcca9b9 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/CheckStaticBlocksTest.xml @@ -56,12 +56,23 @@ <seeInCurrentUrl url="cms/block/new" stepKey="VerifyNewBlockPageIsOpened1"/> <!--Add new BLock with the same data--> <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent1"/> - <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="Default Store View" stepKey="selectDefaultStoreView" /> - <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="{{customStore.name}}" stepKey="selectSecondStoreView1" /> <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="ClickToSaveBlock1"/> <waitForPageLoad stepKey="waitForPageLoad6"/> <!--Verify that corresponding message is displayed--> <see userInput="A block identifier with the same properties already exists in the selected store." stepKey="VerifyBlockIsSaved1"/> + <!--Click to go back and add new block--> + <click selector="{{BlockNewPagePageActionsSection.back}}" stepKey="ClickToGoBack1"/> + <waitForPageLoad stepKey="waitForPageLoad7"/> + <click selector="{{BlockPageActionsSection.addNewBlock}}" stepKey="ClickToAddNewBlock2"/> + <waitForPageLoad stepKey="waitForPageLoad8"/> + <seeInCurrentUrl url="cms/block/new" stepKey="VerifyNewBlockPageIsOpened2"/> + <!--Add new BLock with the same data for another store view--> + <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent2"/> + <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="Default Store View" stepKey="selectDefaultStoreView" /> + <selectOption selector="{{BlockNewPageBasicFieldsSection.storeView}}" userInput="{{customStore.name}}" stepKey="selectSecondStoreView1" /> + <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="ClickToSaveBlock2"/> + <waitForPageLoad stepKey="waitForPageLoad9"/> + <see userInput="You saved the block." stepKey="VerifyBlockIsSaved2"/> <after> <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml index 6569c07f4580a..a73e41de6b861 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/StoreViewLanguageCorrectSwitchTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="NewStoreViewData"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create StoreView --> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml index 944cd02d87b86..58f3b9d5bd3b1 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml @@ -20,7 +20,7 @@ </annotations> <before> <createData entity="_defaultCmsPage" stepKey="createPreReqCMSPage" /> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -91,7 +91,7 @@ <waitForPageLoad stepKey="waitForGridReload"/> <deleteData createDataKey="createPreReqCMSPage" stepKey="deletePreReqCMSPage" /> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml index 24377e92fe083..43615ac906b00 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml @@ -19,7 +19,7 @@ <testCaseId value="MAGETWO-84182 "/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -51,7 +51,7 @@ <see userInput="Hello World!" stepKey="seeContent" /> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Wysiwyg/DirectiveTest.php b/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Wysiwyg/DirectiveTest.php index 5fea276225622..be9f6b8d8ccd5 100644 --- a/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Wysiwyg/DirectiveTest.php +++ b/app/code/Magento/Cms/Test/Unit/Controller/Adminhtml/Wysiwyg/DirectiveTest.php @@ -5,100 +5,123 @@ */ namespace Magento\Cms\Test\Unit\Controller\Adminhtml\Wysiwyg; +use Magento\Backend\App\Action\Context; +use Magento\Cms\Controller\Adminhtml\Wysiwyg\Directive; +use Magento\Cms\Model\Template\Filter; +use Magento\Cms\Model\Wysiwyg\Config; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\Controller\Result\Raw; +use Magento\Framework\Controller\Result\RawFactory; +use Magento\Framework\Filesystem\Driver\File; +use Magento\Framework\Image\Adapter\AdapterInterface; +use Magento\Framework\Image\AdapterFactory; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Url\DecoderInterface; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject; +use Psr\Log\LoggerInterface; + /** * @covers \Magento\Cms\Controller\Adminhtml\Wysiwyg\Directive * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class DirectiveTest extends \PHPUnit\Framework\TestCase +class DirectiveTest extends TestCase { const IMAGE_PATH = 'pub/media/wysiwyg/image.jpg'; /** - * @var \Magento\Cms\Controller\Adminhtml\Wysiwyg\Directive + * @var Directive */ protected $wysiwygDirective; /** - * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var Context|PHPUnit_Framework_MockObject_MockObject */ protected $actionContextMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var RequestInterface|PHPUnit_Framework_MockObject_MockObject */ protected $requestMock; /** - * @var \Magento\Framework\Url\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var DecoderInterface|PHPUnit_Framework_MockObject_MockObject */ protected $urlDecoderMock; /** - * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerInterface|PHPUnit_Framework_MockObject_MockObject */ protected $objectManagerMock; /** - * @var \Magento\Cms\Model\Template\Filter|\PHPUnit_Framework_MockObject_MockObject + * @var Filter|PHPUnit_Framework_MockObject_MockObject */ protected $templateFilterMock; /** - * @var \Magento\Framework\Image\AdapterFactory|\PHPUnit_Framework_MockObject_MockObject + * @var AdapterFactory|PHPUnit_Framework_MockObject_MockObject */ protected $imageAdapterFactoryMock; /** - * @var \Magento\Framework\Image\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + * @var AdapterInterface|PHPUnit_Framework_MockObject_MockObject */ protected $imageAdapterMock; /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ResponseInterface|PHPUnit_Framework_MockObject_MockObject */ protected $responseMock; /** - * @var \Magento\Cms\Model\Wysiwyg\Config|\PHPUnit_Framework_MockObject_MockObject + * @var File|PHPUnit_Framework_MockObject_MockObject + */ + protected $fileMock; + + /** + * @var Config|PHPUnit_Framework_MockObject_MockObject */ protected $wysiwygConfigMock; /** - * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LoggerInterface|PHPUnit_Framework_MockObject_MockObject */ protected $loggerMock; /** - * @var \Magento\Framework\Controller\Result\RawFactory|\PHPUnit_Framework_MockObject_MockObject + * @var RawFactory|PHPUnit_Framework_MockObject_MockObject */ protected $rawFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Raw|\PHPUnit_Framework_MockObject_MockObject + * @var Raw|PHPUnit_Framework_MockObject_MockObject */ protected $rawMock; protected function setUp() { - $this->actionContextMock = $this->getMockBuilder(\Magento\Backend\App\Action\Context::class) + $this->actionContextMock = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->getMock(); - $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) + $this->requestMock = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->urlDecoderMock = $this->getMockBuilder(\Magento\Framework\Url\DecoderInterface::class) + $this->urlDecoderMock = $this->getMockBuilder(DecoderInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + $this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->templateFilterMock = $this->getMockBuilder(\Magento\Cms\Model\Template\Filter::class) + $this->templateFilterMock = $this->getMockBuilder(Filter::class) ->disableOriginalConstructor() ->getMock(); - $this->imageAdapterFactoryMock = $this->getMockBuilder(\Magento\Framework\Image\AdapterFactory::class) + $this->imageAdapterFactoryMock = $this->getMockBuilder(AdapterFactory::class) ->disableOriginalConstructor() ->getMock(); - $this->imageAdapterMock = $this->getMockBuilder(\Magento\Framework\Image\Adapter\AdapterInterface::class) + $this->imageAdapterMock = $this->getMockBuilder(AdapterInterface::class) ->disableOriginalConstructor() ->setMethods( [ @@ -117,21 +140,25 @@ protected function setUp() ] ) ->getMock(); - $this->responseMock = $this->getMockBuilder(\Magento\Framework\App\ResponseInterface::class) + $this->responseMock = $this->getMockBuilder(ResponseInterface::class) ->disableOriginalConstructor() ->setMethods(['setHeader', 'setBody', 'sendResponse']) ->getMock(); - $this->wysiwygConfigMock = $this->getMockBuilder(\Magento\Cms\Model\Wysiwyg\Config::class) + $this->fileMock = $this->getMockBuilder(File::class) ->disableOriginalConstructor() + ->setMethods(['fileGetContents']) ->getMock(); - $this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) + $this->wysiwygConfigMock = $this->getMockBuilder(Config::class) ->disableOriginalConstructor() ->getMock(); - $this->rawFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\RawFactory::class) + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->rawFactoryMock = $this->getMockBuilder(RawFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); - $this->rawMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Raw::class) + $this->rawMock = $this->getMockBuilder(Raw::class) ->disableOriginalConstructor() ->getMock(); @@ -145,9 +172,9 @@ protected function setUp() ->method('getObjectManager') ->willReturn($this->objectManagerMock); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager = new ObjectManager($this); $this->wysiwygDirective = $objectManager->getObject( - \Magento\Cms\Controller\Adminhtml\Wysiwyg\Directive::class, + Directive::class, [ 'context' => $this->actionContextMock, 'urlDecoder' => $this->urlDecoderMock, @@ -155,7 +182,8 @@ protected function setUp() 'adapterFactory' => $this->imageAdapterFactoryMock, 'logger' => $this->loggerMock, 'config' => $this->wysiwygConfigMock, - 'filter' => $this->templateFilterMock + 'filter' => $this->templateFilterMock, + 'file' => $this->fileMock, ] ); } @@ -172,23 +200,29 @@ public function testExecute() $this->imageAdapterMock->expects($this->once()) ->method('open') ->with(self::IMAGE_PATH); - $this->imageAdapterMock->expects($this->once()) + $this->imageAdapterMock->expects($this->atLeastOnce()) ->method('getMimeType') ->willReturn($mimeType); - $this->rawMock->expects($this->once()) + $this->rawMock->expects($this->atLeastOnce()) ->method('setHeader') ->with('Content-Type', $mimeType) ->willReturnSelf(); - $this->rawMock->expects($this->once()) + $this->rawMock->expects($this->atLeastOnce()) ->method('setContents') ->with($imageBody) ->willReturnSelf(); $this->imageAdapterMock->expects($this->once()) ->method('getImage') ->willReturn($imageBody); + $this->fileMock->expects($this->once()) + ->method('fileGetContents') + ->willReturn($imageBody); $this->rawFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->rawMock); + $this->imageAdapterFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->imageAdapterMock); $this->assertSame( $this->rawMock, @@ -217,20 +251,23 @@ public function testExecuteException() $this->imageAdapterMock->expects($this->at(1)) ->method('open') ->with($placeholderPath); - $this->imageAdapterMock->expects($this->once()) + $this->imageAdapterMock->expects($this->atLeastOnce()) ->method('getMimeType') ->willReturn($mimeType); - $this->rawMock->expects($this->once()) + $this->rawMock->expects($this->atLeastOnce()) ->method('setHeader') ->with('Content-Type', $mimeType) ->willReturnSelf(); - $this->rawMock->expects($this->once()) + $this->rawMock->expects($this->atLeastOnce()) ->method('setContents') ->with($imageBody) ->willReturnSelf(); - $this->imageAdapterMock->expects($this->once()) + $this->imageAdapterMock->expects($this->any()) ->method('getImage') ->willReturn($imageBody); + $this->fileMock->expects($this->once()) + ->method('fileGetContents') + ->willReturn($imageBody); $this->loggerMock->expects($this->once()) ->method('warning') ->with($exception); @@ -238,6 +275,10 @@ public function testExecuteException() ->method('create') ->willReturn($this->rawMock); + $this->imageAdapterFactoryMock->expects($this->exactly(1)) + ->method('create') + ->willReturn($this->imageAdapterMock); + $this->assertSame( $this->rawMock, $this->wysiwygDirective->execute() @@ -297,6 +338,20 @@ public function testExecuteWithDeletedImage() ->method('warning') ->with($exception); + $this->rawMock->expects($this->once()) + ->method('setHeader') + ->with('Content-Type', null) + ->willReturnSelf(); + + $this->rawMock->expects($this->once()) + ->method('setContents') + ->with(null) + ->willReturnSelf(); + + $this->rawFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->rawMock); + $this->wysiwygDirective->execute(); } } diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php index 53d8ee5220768..781d6d31246ca 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php @@ -3,91 +3,112 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Cms\Test\Unit\Ui\Component\Listing\Column; use Magento\Cms\Ui\Component\Listing\Column\PageActions; +use Magento\Cms\ViewModel\Page\Grid\UrlBuilder; use Magento\Framework\Escaper; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\UrlInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\Processor; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Test for Magento\Cms\Ui\Component\Listing\Column\PageActions class. */ -class PageActionsTest extends \PHPUnit\Framework\TestCase +class PageActionsTest extends TestCase { - public function testPrepareItemsByPageId() + + /** + * @var UrlInterface|MockObject + */ + private $urlBuilderMock; + + /** + * @var UrlBuilder|MockObject + */ + private $scopeUrlBuilderMock; + + /** + * @var ContextInterface|MockObject + */ + private $contextMock; + + /** + * @var Processor|MockObject + */ + private $processorMock; + + /** + * @var Escaper|MockObject + */ + private $escaperMock; + + /** + * @var PageActions + */ + private $model; + + /** + * @inheritDoc + */ + public function setUp() { - $pageId = 1; - // Create Mocks and SUT - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - /** @var \PHPUnit_Framework_MockObject_MockObject $urlBuilderMock */ - $urlBuilderMock = $this->getMockBuilder(\Magento\Framework\UrlInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $contextMock = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\ContextInterface::class) + $this->urlBuilderMock = $this->createMock(UrlInterface::class); + $this->scopeUrlBuilderMock = $this->createMock(UrlBuilder::class); + $this->processorMock = $this->createMock(Processor::class); + $this->contextMock = $this->getMockBuilder(ContextInterface::class) ->getMockForAbstractClass(); - $processor = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\Processor::class) + $this->escaperMock = $this->getMockBuilder(Escaper::class) ->disableOriginalConstructor() + ->setMethods(['escapeHtml']) ->getMock(); - $contextMock->expects($this->never())->method('getProcessor')->willReturn($processor); - /** @var \Magento\Cms\Ui\Component\Listing\Column\PageActions $model */ - $model = $objectManager->getObject( - \Magento\Cms\Ui\Component\Listing\Column\PageActions::class, + $objectManager = new ObjectManager($this); + + $this->model = $objectManager->getObject( + PageActions::class, [ - 'urlBuilder' => $urlBuilderMock, - 'context' => $contextMock, + 'urlBuilder' => $this->urlBuilderMock, + 'context' => $this->contextMock, + 'scopeUrlBuilder' => $this->scopeUrlBuilderMock ] ); - $escaper = $this->getMockBuilder(Escaper::class) - ->disableOriginalConstructor() - ->setMethods(['escapeHtml']) - ->getMock(); - $objectManager->setBackwardCompatibleProperty($model, 'escaper', $escaper); - - // Define test input and expectations - $title = 'page title'; - $items = [ - 'data' => [ - 'items' => [ - [ - 'page_id' => $pageId, - 'title' => $title - ] - ] - ] - ]; - $name = 'item_name'; - $expectedItems = [ - [ - 'page_id' => $pageId, - 'title' => $title, - $name => [ - 'edit' => [ - 'href' => 'test/url/edit', - 'label' => __('Edit'), - '__disableTmpl' => true, - ], - 'delete' => [ - 'href' => 'test/url/delete', - 'label' => __('Delete'), - 'confirm' => [ - 'title' => __('Delete %1', $title), - 'message' => __('Are you sure you want to delete a %1 record?', $title), - '__disableTmpl' => true, - ], - 'post' => true, - '__disableTmpl' => true, - ], - ], - ], - ]; + $objectManager->setBackwardCompatibleProperty($this->model, 'escaper', $this->escaperMock); + } - $escaper->expects(static::once()) + /** + * Verify Prepare Items by page Id. + * + * @dataProvider configDataProvider + * @param int $pageId + * @param string $title + * @param string $name + * @param array $items + * @param array $expectedItems + * @return void + */ + public function testPrepareItemsByPageId( + int $pageId, + string $title, + string $name, + array $items, + array $expectedItems + ):void { + $this->contextMock->expects($this->never()) + ->method('getProcessor') + ->willReturn($this->processorMock); + $this->escaperMock->expects(static::once()) ->method('escapeHtml') ->with($title) ->willReturn($title); // Configure mocks and object data - $urlBuilderMock->expects($this->any()) + $this->urlBuilderMock->expects($this->any()) ->method('getUrl') ->willReturnMap( [ @@ -107,9 +128,77 @@ public function testPrepareItemsByPageId() ], ] ); - $model->setName($name); - $items = $model->prepareDataSource($items); + + $this->scopeUrlBuilderMock->expects($this->any()) + ->method('getUrl') + ->willReturn('test/url/view'); + + $this->model->setName($name); + $items = $this->model->prepareDataSource($items); // Run test $this->assertEquals($expectedItems, $items['data']['items']); } + + /** + * Data provider for testPrepareItemsByPageId + * + * @return array + */ + public function configDataProvider():array + { + $pageId = 1; + $title = 'page title'; + $identifier = 'page_identifier'; + $name = 'item_name'; + + return [ + [ + 'pageId' => $pageId, + 'title' => $title, + 'name' => $name, + 'items' => [ + 'data' => [ + 'items' => [ + [ + 'page_id' => $pageId, + 'title' => $title, + 'identifier' => $identifier + ] + ] + ] + ], + 'expectedItems' => [ + [ + 'page_id' => $pageId, + 'title' => $title, + 'identifier' => $identifier, + $name => [ + 'edit' => [ + 'href' => 'test/url/edit', + 'label' => __('Edit'), + '__disableTmpl' => true, + ], + 'delete' => [ + 'href' => 'test/url/delete', + 'label' => __('Delete'), + 'confirm' => [ + 'title' => __('Delete %1', $title), + 'message' => __('Are you sure you want to delete a %1 record?', $title), + '__disableTmpl' => true, + ], + 'post' => true, + '__disableTmpl' => true, + ], + 'preview' => [ + 'href' => 'test/url/view', + 'label' => __('View'), + '__disableTmpl' => true, + 'target' => '_blank' + ] + ], + ], + ] + ] + ]; + } } diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php index fa3756abfded4..0c6000bdbab84 100644 --- a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php @@ -14,7 +14,7 @@ use Magento\Ui\Component\Listing\Columns\Column; /** - * Class PageActions + * Class prepare Page Actions */ class PageActions extends Column { @@ -111,6 +111,7 @@ public function prepareDataSource(array $dataSource) ), 'label' => __('View'), '__disableTmpl' => true, + 'target' => '_blank' ]; } } diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml index 793fc7d26cb4a..af54df24b64f5 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml @@ -146,6 +146,7 @@ <editor> <validation> <rule name="required-entry" xsi:type="boolean">true</rule> + <rule name="no-marginal-whitespace" xsi:type="boolean">true</rule> </validation> <editorType>text</editorType> </editor> diff --git a/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php b/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php index 23a3dea1a7029..c4a0cb5e886d9 100644 --- a/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php +++ b/app/code/Magento/Config/Model/Config/Structure/AbstractElement.php @@ -103,7 +103,7 @@ public function getData() */ public function getId() { - return isset($this->_data['id']) ? $this->_data['id'] : ''; + return $this->_data['id'] ?? ''; } /** @@ -133,7 +133,7 @@ public function getComment() */ public function getFrontendModel() { - return isset($this->_data['frontend_model']) ? $this->_data['frontend_model'] : ''; + return $this->_data['frontend_model'] ?? ''; } /** @@ -194,7 +194,7 @@ protected function _hasVisibilityValue($key) */ public function getClass() { - return isset($this->_data['class']) ? $this->_data['class'] : ''; + return $this->_data['class'] ?? ''; } /** diff --git a/app/code/Magento/Config/Model/Config/Structure/Element/Field.php b/app/code/Magento/Config/Model/Config/Structure/Element/Field.php index 834b2a9e17e37..2a4397b3300c0 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Element/Field.php +++ b/app/code/Magento/Config/Model/Config/Structure/Element/Field.php @@ -150,7 +150,7 @@ public function getTooltip() */ public function getType() { - return isset($this->_data['type']) ? $this->_data['type'] : 'text'; + return $this->_data['type'] ?? 'text'; } /** @@ -204,7 +204,7 @@ public function getRequiredFields($fieldPrefix = '') */ public function getFrontendClass() { - return isset($this->_data['frontend_class']) ? $this->_data['frontend_class'] : ''; + return $this->_data['frontend_class'] ?? ''; } /** @@ -256,7 +256,7 @@ public function getGroupPath() */ public function getConfigPath() { - return isset($this->_data['config_path']) ? $this->_data['config_path'] : null; + return $this->_data['config_path'] ?? null; } /** @@ -334,7 +334,7 @@ public function hasValidation() */ public function getValidation() { - return isset($this->_data['validate']) ? $this->_data['validate'] : null; + return $this->_data['validate'] ?? null; } /** diff --git a/app/code/Magento/Config/Model/Config/Structure/Element/Section.php b/app/code/Magento/Config/Model/Config/Structure/Element/Section.php index 80c029dfea2d0..15f590dfd2ffa 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Element/Section.php +++ b/app/code/Magento/Config/Model/Config/Structure/Element/Section.php @@ -6,7 +6,7 @@ namespace Magento\Config\Model\Config\Structure\Element; /** - * Section + * Element section * * @api * @since 100.0.2 @@ -43,7 +43,7 @@ public function __construct( */ public function getHeaderCss() { - return isset($this->_data['header_css']) ? $this->_data['header_css'] : ''; + return $this->_data['header_css'] ?? ''; } /** diff --git a/app/code/Magento/Config/Test/Mftf/Test/CheckingCountryDropDownWithOneAllowedCountryTest.xml b/app/code/Magento/Config/Test/Mftf/Test/CheckingCountryDropDownWithOneAllowedCountryTest.xml index 1d54f2ef52c02..32fa1d13023de 100644 --- a/app/code/Magento/Config/Test/Mftf/Test/CheckingCountryDropDownWithOneAllowedCountryTest.xml +++ b/app/code/Magento/Config/Test/Mftf/Test/CheckingCountryDropDownWithOneAllowedCountryTest.xml @@ -30,7 +30,7 @@ </actionGroup> <actionGroup ref="AdminClearCustomersFiltersActionGroup" stepKey="clearFilters"/> <waitForPageLoad stepKey="WaitForPageToLoad"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Flush Magento Cache--> <magentoCLI stepKey="flushCache" command="cache:flush"/> diff --git a/app/code/Magento/Config/Test/Mftf/Test/ConfigurationTest.xml b/app/code/Magento/Config/Test/Mftf/Test/ConfigurationTest.xml index 66aacf706b039..916a5a09a09c0 100644 --- a/app/code/Magento/Config/Test/Mftf/Test/ConfigurationTest.xml +++ b/app/code/Magento/Config/Test/Mftf/Test/ConfigurationTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{CatalogConfigPage.url}}" stepKey="navigateToConfigurationPage" /> <waitForPageLoad stepKey="waitForPageLoad"/> diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index fa677b0b8b421..1b3ecfb1d222a 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -1270,14 +1270,8 @@ private function getCatalogConfig() */ public function isPossibleBuyFromList($product) { - $isAllCustomOptionsDisplayed = true; - foreach ($this->getConfigurableAttributes($product) as $attribute) { - $eavAttribute = $attribute->getProductAttribute(); - - $isAllCustomOptionsDisplayed = ($isAllCustomOptionsDisplayed && $eavAttribute->getUsedInProductListing()); - } - - return $isAllCustomOptionsDisplayed; + //such cases already handled by add to cart action + return true; } /** diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php index 447ba16d72710..4be124f6d9e5b 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php @@ -9,8 +9,6 @@ /** * Responsible for displaying tier price box on configurable product page. - * - * @package Magento\ConfigurableProduct\Pricing\Render */ class TierPriceBox extends FinalPriceBox { @@ -23,6 +21,7 @@ public function toHtml() if (!$this->isMsrpPriceApplicable() && $this->isTierPriceApplicable()) { return parent::toHtml(); } + return ''; } /** diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/CreateApiConfigurableProductWithProductAttributeAdvanceSearchActionGroup.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/CreateApiConfigurableProductWithProductAttributeAdvanceSearchActionGroup.xml new file mode 100644 index 0000000000000..77fcc137a0db5 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/ActionGroup/CreateApiConfigurableProductWithProductAttributeAdvanceSearchActionGroup.xml @@ -0,0 +1,21 @@ +<?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="CreateApiConfigurableProductWithDescriptionActionGroup" extends="AdminCreateApiConfigurableProductActionGroup"> + <annotations> + <description>Creates a Configurable Product with Description and 2 Product Options via API.</description> + </annotations> + + <!-- Replacement action. Create the configurable product via API. --> + <createData entity="ApiConfigurableProductWithDescription" stepKey="createConfigProduct"> + <field key="name">{{productName}}</field> + </createData> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml index 3edb7c0f17ab9..87b181616bd7a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Data/ConfigurableProductData.xml @@ -23,12 +23,12 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="ApiConfigurableProduct" type="product"> + <data key="name" unique="suffix">API Configurable Product</data> <data key="sku" unique="suffix">api-configurable-product</data> + <data key="urlKey" unique="suffix">api-configurable-product</data> <data key="type_id">configurable</data> <data key="attribute_set_id">4</data> <data key="visibility">4</data> - <data key="name" unique="suffix">API Configurable Product</data> - <data key="urlKey" unique="suffix">api-configurable-product</data> <data key="price">123.00</data> <data key="weight">2</data> <data key="status">1</data> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index 0853d22eda7b9..cf0e99f7c45c0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontProductInfoMainSection"> <element name="optionByAttributeId" type="input" selector="#attribute{{var1}}" parameterized="true"/> + <element name="selectableProductOptions" type="select" selector="#attribute{{var1}} option:not([disabled])" parameterized="true"/> <element name="productAttributeTitle1" type="text" selector="#product-options-wrapper div[tabindex='0'] label"/> <element name="productPrice" type="text" selector="div.price-box.price-final_price"/> <element name="productAttributeOptions1" type="select" selector="#product-options-wrapper div[tabindex='0'] option"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml index 2f9347157ef33..a10545ba415fe 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddDefaultImageConfigurableTest.xml @@ -89,6 +89,9 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="productIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml index a70a62470ecbc..543ead3f6732a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml @@ -34,7 +34,7 @@ <actionGroup ref="DeleteProductActionGroup" stepKey="deleteProduct1"> <argument name="productName" value="$$createConfigProductCreateConfigurableProduct.name$$"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open edit product page--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAssertNoticeThatExistingSkuAutomaticallyChangedWhenSavingProductWithSameSkuTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAssertNoticeThatExistingSkuAutomaticallyChangedWhenSavingProductWithSameSkuTest.xml index 1613452dfc47c..a6c3794a2d622 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAssertNoticeThatExistingSkuAutomaticallyChangedWhenSavingProductWithSameSkuTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAssertNoticeThatExistingSkuAutomaticallyChangedWhenSavingProductWithSameSkuTest.xml @@ -32,7 +32,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml index 98cb03916bdab..79d109de31821 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml @@ -33,7 +33,10 @@ <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridColumnsInitial"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product--> <comment userInput="Create configurable product" stepKey="createConfProd"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml index fabd4a2c253b6..7843d387eb2b9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml @@ -109,7 +109,10 @@ <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductAttributesFilter"/> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilter"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create three configurable products with options --> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml index 5bdccf15b19d3..635e4c6f84c72 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml @@ -43,7 +43,10 @@ <actionGroup ref="DeleteProductAttributeActionGroup" stepKey="deleteAttribute"> <argument name="ProductAttribute" value="productDropDownAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductCreateTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductCreateTest.xml index 2a1c38ee135eb..692ba32c6db28 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductCreateTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductCreateTest.xml @@ -26,7 +26,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a configurable product via the UI --> @@ -92,7 +92,7 @@ <after> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductEditPage.url($$createConfigProduct.id$$)}}" stepKey="goToEditPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml index 83e428b454c46..eabeb1b6881a0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml @@ -66,10 +66,13 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- assert product visible in storefront --> @@ -216,7 +219,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> @@ -225,6 +228,9 @@ <deleteData createDataKey="createConfigChildProduct6" stepKey="deleteConfigChildProduct6"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Search for prefix of the 3 products we created via api --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml index baea299581052..24a7a590566bd 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml @@ -52,7 +52,10 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <!--Clean up category--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create a configurable product with long name and sku--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml index 6bba4aa6b43ce..2ab3a9e6e60c9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml @@ -77,12 +77,15 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> @@ -200,10 +203,13 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> @@ -301,11 +307,14 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Check to make sure that the configurable product shows up as in stock --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml index 889ca5b24b242..7c20574868a66 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml @@ -68,11 +68,14 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> @@ -147,11 +150,14 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml index c437b39a405cd..fc10b2cc3b4e3 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml @@ -96,7 +96,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <!-- Delete everything that was created in the before block --> <deleteData createDataKey="createCategory" stepKey="deleteCatagory" /> @@ -105,6 +105,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createModifiableProductAttribute" stepKey="deleteModifiableProductAttribute"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Get the current option of the attribute before it was changed --> @@ -213,7 +216,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <!-- Delete everything that was created in the before block --> <deleteData createDataKey="createCategory" stepKey="deleteCatagory" /> @@ -221,6 +224,9 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Find the product that we just created using the product grid --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml index da0c5a65f944d..be039eb2f3389 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml @@ -41,7 +41,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> <waitForPageLoad stepKey="waitForPageLoad"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search for prefix of the 3 products we created via api --> @@ -145,6 +145,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--check storefront for both options--> @@ -238,6 +241,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--check storefront for both options--> @@ -280,7 +286,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a configurable product via the UI --> @@ -329,7 +335,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a configurable product via the UI --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml index bba8232139d69..924707a16600f 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml @@ -21,6 +21,8 @@ </annotations> <before> <createData entity="ApiCategory" stepKey="createCategory"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Delete configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndEditConfigurableProductSettingsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndEditConfigurableProductSettingsTest.xml index 6632cbcee30f2..2503af780d5d3 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndEditConfigurableProductSettingsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndEditConfigurableProductSettingsTest.xml @@ -24,7 +24,7 @@ </before> <after> <!-- Log out --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml index fa515c89fa460..7e2639c7e6e25 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateAndSwitchProductType.xml @@ -149,7 +149,7 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> <deleteData stepKey="deleteAttribute" createDataKey="createConfigProductAttribute"/> <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product from downloadable product page--> <comment userInput="Create configurable product" stepKey="commentCreateProduct"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductBasedOnParentSkuTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductBasedOnParentSkuTest.xml index 578e908664ecb..41ba0fc048120 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductBasedOnParentSkuTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductBasedOnParentSkuTest.xml @@ -32,7 +32,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithCreatingCategoryAndAttributeTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithCreatingCategoryAndAttributeTest.xml index 363daa0ec8bb2..cef95ec7835d0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithCreatingCategoryAndAttributeTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithCreatingCategoryAndAttributeTest.xml @@ -49,7 +49,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml index f64ba4a63cec9..586a22982b334 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml @@ -53,7 +53,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml index b448131e75f15..7f03efbc7fd65 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml @@ -56,7 +56,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml index 1c6908818b4da..41a446e6bc320 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml @@ -76,7 +76,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml index 1b7fc2c153208..95891b286ab53 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml @@ -75,7 +75,10 @@ <magentoCLI command="cron:run --group=index" stepKey="runCron"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml index e67788d5e7bb0..f9729c42f0acf 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml @@ -64,7 +64,10 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsAssignedToCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsAssignedToCategoryTest.xml index 6ab4734a074a5..4c39b0c2a54fb 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsAssignedToCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsAssignedToCategoryTest.xml @@ -52,7 +52,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsWithoutAssignedToCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsWithoutAssignedToCategoryTest.xml index 14303aa9b650b..31851fc78968b 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsWithoutAssignedToCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTwoOptionsWithoutAssignedToCategoryTest.xml @@ -45,7 +45,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create configurable product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminDeleteConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminDeleteConfigurableProductTest.xml index c2edbaa4e6e87..68f86a7d07890 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminDeleteConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminDeleteConfigurableProductTest.xml @@ -26,7 +26,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteConfigurableProductFilteredBySkuAndName"> <argument name="product" value="$$createConfigurableProduct$$"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml index f1535d62861ac..e308bafb2ac46 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml @@ -43,7 +43,10 @@ <argument name="product" value="$$createProduct$$"/> </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Add configurations to product--> <comment userInput="Add configurations to product" stepKey="commentAddConfigs"/> @@ -147,7 +150,10 @@ <argument name="product" value="$$createProduct$$"/> </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Add configurations to product--> <comment userInput="Add configurations to product" stepKey="commentAddConfigurations"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml index 710430cf123dc..d764876d3b5cc 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRelatedProductsTest.xml @@ -89,6 +89,9 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <comment userInput="Filter and edit simple product 1" stepKey="filterAndEditComment1"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml index 0cc73f117aaad..e0c4fda005666 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminRemoveDefaultImageConfigurableTest.xml @@ -89,6 +89,8 @@ <deleteData createDataKey="baseConfigProductHandle" stepKey="deleteConfig"/> <deleteData createDataKey="categoryHandle" stepKey="deleteCategory"/> <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductAttribute"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="productIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml index 0370280309272..05a9222eacaf9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdvanceCatalogSearchConfigurableTest.xml @@ -82,6 +82,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableBySkuTest" extends="AdvanceCatalogSearchSimpleProductBySkuTest"> @@ -158,6 +162,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableByDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByDescriptionTest"> @@ -234,6 +242,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> <test name="AdvanceCatalogSearchConfigurableByShortDescriptionTest" extends="AdvanceCatalogSearchSimpleProductByShortDescriptionTest"> @@ -310,6 +322,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml index 124f0eea2e77a..49a1ab6b5e11d 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml @@ -77,7 +77,9 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteSecondWebsite"> <argument name="websiteName" value="Second Website"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="EnableWebUrlOptionsActionGroup" stepKey="addStoreCodeToUrls"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml index 59bb7f53f0aa8..a4904c67e0ef8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CGuestUserTest.xml @@ -73,6 +73,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> @@ -282,6 +285,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml index dd0673563838e..847ee728d5e78 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml @@ -61,6 +61,8 @@ <requiredEntity createDataKey="createConfigProduct"/> </createData> <updateData entity="ApiSimpleProductUpdateDescription" stepKey="updateConfigProduct" createDataKey="createConfigProduct"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </before> <after> <!-- @TODO: Uncomment once MQE-679 is fixed --> @@ -73,6 +75,9 @@ <!--<deleteData createDataKey="createConfigProductImage" stepKey="deleteConfigProductImage"/>--> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Verify Configurable Product in checkout cart items --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml index eadc7dadaf708..5caba34def165 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NewProductsListWidgetConfigurableProductTest.xml @@ -70,6 +70,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- A Cms page containing the New Products Widget gets created here via extends --> @@ -88,4 +91,4 @@ <waitForPageLoad stepKey="waitForCmsPage"/> <see selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" userInput="$$createConfigProduct.name$$" stepKey="seeProductName"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml index 914550fabf39b..18993269ab0b1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml @@ -35,7 +35,7 @@ <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go To Created Product Page --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml index 5224cc6a9cced..55a109aee4b37 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml @@ -102,7 +102,10 @@ <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCreatedCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Disable child product --> <comment userInput="Disable child product" stepKey="disableChildProduct"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml index 6045ca5567b45..24c60006a3504 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ProductsQtyReturnAfterOrderCancelTest.xml @@ -32,7 +32,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <amOnPage url="{{AdminCatalogProductPage.url}}" stepKey="GoToCatalogProductPage1"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml index a8e982475253f..020e5dbbdfc77 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontAdvanceCatalogSearchConfigurableBySkuWithHyphenTest.xml @@ -83,6 +83,10 @@ <deleteData createDataKey="simple2Handle" stepKey="deleteSimple2" before="delete"/> <deleteData createDataKey="childProductHandle1" stepKey="deleteChildProduct1" before="delete"/> <deleteData createDataKey="childProductHandle2" stepKey="deleteChildProduct2" before="delete"/> + <deleteData createDataKey="productAttributeHandle" stepKey="deleteProductDropDownAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml index 294ab9fd0664d..eaf9fa689d218 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml @@ -132,7 +132,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> @@ -140,6 +140,9 @@ <deleteData createDataKey="createConfigProductAttributeMultiSelect" stepKey="deleteConfigProductAttributeMultiSelect"/> <deleteData createDataKey="createConfigProductAttributeSelect" stepKey="deleteConfigProductAttributeSelect"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Quick search the storefront for the first attribute option --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml index 42b9dfc92760a..387f2e212c4aa 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml @@ -35,7 +35,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify configurable product details in storefront product view --> @@ -80,7 +80,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify configurable product options in storefront product view --> @@ -125,7 +125,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify adding configurable product to cart after an option is selected in storefront product view --> @@ -167,7 +167,7 @@ <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify not able to add configurable product to cart when no option is selected in storefront product view --> @@ -219,7 +219,10 @@ <deleteData createDataKey="createFirstAttribute" stepKey="deleteFirstAttribute"/> <deleteData createDataKey="createSecondAttribute" stepKey="deleteSecondAttribute"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPage"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductViewTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductViewTest.xml index bfdadd54b872c..7e9ee68b9f2f7 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductViewTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductViewTest.xml @@ -37,7 +37,7 @@ <actionGroup stepKey="deleteProduct" ref="DeleteProductBySkuActionGroup"> <argument name="sku" value="{{_defaultProduct.sku}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify the storefront category grid view --> @@ -73,7 +73,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Verify storefront category list view --> @@ -111,7 +111,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Should be taken to product details page when adding to cart because an option needs to be selected --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductWithFileCustomOptionTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductWithFileCustomOptionTest.xml index e24c8e4d94916..4de8dedefab48 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductWithFileCustomOptionTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductWithFileCustomOptionTest.xml @@ -25,7 +25,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml index 56e5bedc9eab1..fc32a1ca6ac8c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml @@ -94,7 +94,10 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Go to the product page for the first product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 15df342ca47a8..fcb9811a93dfa 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -99,8 +99,8 @@ <argument name="option" value="Yes"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> - <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> - <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> + + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </before> <after> @@ -121,10 +121,10 @@ <argument name="option" value="No"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> - <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> - <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Open category with products and Sort by price desc--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml index 3ebd9d6ef5367..32f9d78828ed1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml @@ -116,7 +116,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Open Product Index Page and Filter First Child product --> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml index b8b0007c63d5f..6befc15044cc5 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVisibilityOfDuplicateProductTest.xml @@ -45,7 +45,7 @@ </actionGroup> <click selector="{{AdminProductAttributeGridSection.ResetFilter}}" stepKey="resetFiltersOnGridSecond"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create attribute and options for product--> <comment userInput="Create attribute and options for product" stepKey="commentCreateAttributesAndOptions"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php new file mode 100644 index 0000000000000..95f592daaa06a --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Render; + +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface; +use Magento\Catalog\Pricing\Price\MinimalPriceCalculatorInterface; +use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Render\TierPriceBox; +use Magento\Framework\Pricing\Price\PriceInterface; +use Magento\Framework\Pricing\PriceInfoInterface; +use Magento\Framework\Pricing\Render\RendererPool; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\Template\Context; +use Magento\Msrp\Pricing\Price\MsrpPrice; +use PHPUnit\Framework\MockObject\MockObject; + +class TierPriceBoxTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Context|MockObject + */ + private $context; + + /** + * @var Product|MockObject + */ + private $saleableItem; + + /** + * @var PriceInterface|MockObject + */ + private $price; + + /** + * @var RendererPool|MockObject + */ + private $rendererPool; + + /** + * @var SalableResolverInterface|MockObject + */ + private $salableResolver; + + /** + * @var MinimalPriceCalculatorInterface|MockObject + */ + private $minimalPriceCalculator; + + /** + * @var ConfigurableOptionsProviderInterface|MockObject + */ + private $configurableOptionsProvider; + + /** + * @var TierPriceBox + */ + private $model; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->context = $this->createPartialMock(Context::class, []); + $this->saleableItem = $this->createPartialMock(Product::class, ['getPriceInfo']); + $this->price = $this->createMock(PriceInterface::class); + $this->rendererPool = $this->createPartialMock(RendererPool::class, []); + $this->salableResolver = $this->createPartialMock(SalableResolverInterface::class, ['isSalable']); + $this->minimalPriceCalculator = $this->createMock(MinimalPriceCalculatorInterface::class); + $this->configurableOptionsProvider = $this->createMock(ConfigurableOptionsProviderInterface::class); + + $this->model = (new ObjectManager($this))->getObject( + TierPriceBox::class, + [ + 'context' => $this->context, + 'saleableItem' => $this->saleableItem, + 'price' => $this->price, + 'rendererPool' => $this->rendererPool, + 'salableResolver' => $this->salableResolver, + 'minimalPriceCalculator' => $this->minimalPriceCalculator, + 'configurableOptionsProvider' => $this->configurableOptionsProvider, + ] + ); + } + + public function testToHtmlEmptyWhenMsrpPriceIsApplicable(): void + { + $msrpPriceMock = $this->createPartialMock( + MsrpPrice::class, + ['canApplyMsrp', 'isMinimalPriceLessMsrp'] + ); + $msrpPriceMock->expects($this->once()) + ->method('canApplyMsrp') + ->willReturn(true); + $msrpPriceMock->expects($this->once()) + ->method('isMinimalPriceLessMsrp') + ->willReturn(true); + + $priceInfoMock = $this->createMock(PriceInfoInterface::class); + $priceInfoMock->expects($this->once()) + ->method('getPrice') + ->willReturn($msrpPriceMock); + + $this->saleableItem->expects($this->once()) + ->method('getPriceInfo') + ->willReturn($priceInfoMock); + + $result = $this->model->toHtml(); + $this->assertSame('', $result); + } +} diff --git a/app/code/Magento/Contact/view/frontend/templates/form.phtml b/app/code/Magento/Contact/view/frontend/templates/form.phtml index 3a7c4c8b6d865..d218e650657ac 100644 --- a/app/code/Magento/Contact/view/frontend/templates/form.phtml +++ b/app/code/Magento/Contact/view/frontend/templates/form.phtml @@ -52,7 +52,7 @@ $viewModel = $block->getViewModel(); title="<?= $block->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $block->escapeHtmlAttr($viewModel->getUserTelephone()) ?>" class="input-text" - type="text" /> + type="tel" /> </div> </div> <div class="field comment required"> diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js index 2c4a070130804..d61f8f9d32523 100644 --- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js +++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js @@ -30,6 +30,7 @@ define([ if ($.mage.cookies.get(this.options.cookieName)) { this.element.hide(); + $(document).trigger('user:allowed:save:cookie'); } else { window.location.href = this.options.noCookiesUrl; } diff --git a/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php b/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php index 285d37a1b6270..ed4d4a6fde51d 100644 --- a/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php +++ b/app/code/Magento/Csp/Model/Collector/CspWhitelistXml/SchemaLocator.php @@ -22,7 +22,7 @@ class SchemaLocator implements SchemaLocatorInterface * * @var string */ - private $schema ; + private $schema; /** * @param Reader $moduleReader diff --git a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php new file mode 100644 index 0000000000000..8c42a4d051bde --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Csp\Test\Unit\Observer; + +use Magento\Csp\Api\CspRendererInterface; +use Magento\Csp\Observer\Render; +use Magento\Framework\App\Response\Http as ResponseHttp; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Csp\Observer\Render + */ +class RenderTest extends TestCase +{ + /** + * Check if the render method is called + */ + public function testExecuteExpectsRenderCalled() + { + $eventMock = $this->createMock(Event::class); + $responseMock = $this->createMock(ResponseHttp::class); + $eventMock->expects($this->once()) + ->method('getData') + ->with('response') + ->willReturn($responseMock); + + /** @var MockObject|Observer $eventObserverMock */ + $eventObserverMock = $this->createMock(Observer::class); + $eventObserverMock->expects($this->once())->method('getEvent')->willReturn($eventMock); + + $cspRendererMock = $this->createMock(CspRendererInterface::class); + $cspRendererMock->expects($this->once())->method('render'); + + $objectManagerHelper = new ObjectManager($this); + /** @var Render $renderObserver */ + $renderObserver = $objectManagerHelper->getObject( + Render::class, + ['cspRenderer' => $cspRendererMock] + ); + $renderObserver->execute($eventObserverMock); + } +} diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminCurrencyConverterAPIConfigurationTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminCurrencyConverterAPIConfigurationTest.xml index 6232f59bb839a..eb3ca4f977c65 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminCurrencyConverterAPIConfigurationTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminCurrencyConverterAPIConfigurationTest.xml @@ -40,7 +40,7 @@ <!--Delete created data--> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Import rates from Currency Converter API--> <amOnPage url="{{AdminCurrencyRatesPage.url}}" stepKey="onCurrencyRatePage"/> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml index a04128c3d5ded..7e1cb41871d43 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml @@ -23,7 +23,7 @@ </before> <after> <magentoCLI command="config:set --scope={{SetAllowedCurrenciesConfigForUSD.scope}} --scope-code={{SetAllowedCurrenciesConfigForUSD.scope_code}} {{SetAllowedCurrenciesConfigForUSD.path}} {{SetAllowedCurrenciesConfigForUSD.value}},{{SetAllowedCurrenciesConfigForEUR.value}}" stepKey="setAllowedCurrencyWebsites_EUR_USD"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateToCurrencySymbolsPageActionGroup" stepKey="navigateToCurrencySymbolsPage"/> <actionGroup ref="AssertAdminCurrencySymbolIsDisabledActionGroup" stepKey="assertEURDisabledInput"> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayWhenChooseThreeAllowedCurrenciesTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayWhenChooseThreeAllowedCurrenciesTest.xml index 100aa39613b33..8f87246bcf018 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayWhenChooseThreeAllowedCurrenciesTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayWhenChooseThreeAllowedCurrenciesTest.xml @@ -32,7 +32,7 @@ <!--Delete created product--> <comment userInput="Delete created product" stepKey="commentDeleteCreatedProduct"/> <deleteData createDataKey="createNewProduct" stepKey="deleteNewProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Set currency rates--> <amOnPage url="{{AdminCurrencyRatesPage.url}}" stepKey="gotToCurrencyRatesPageSecondTime"/> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayedInOneLineTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayedInOneLineTest.xml index 94c9bc67e34c4..8c61bd4434fff 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayedInOneLineTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminOrderRateDisplayedInOneLineTest.xml @@ -46,7 +46,7 @@ <magentoCLI command="config:set --scope={{SetCurrencyUSDBaseConfig.scope}} --scope-code={{SetCurrencyUSDBaseConfig.scope_code}} {{SetCurrencyUSDBaseConfig.path}} {{SetCurrencyUSDBaseConfig.value}}" stepKey="setCurrencyBaseUSDWebsites"/> <magentoCLI command="config:set --scope={{SetDefaultCurrencyUSDConfig.scope}} --scope-code={{SetDefaultCurrencyUSDConfig.scope_code}} {{SetDefaultCurrencyUSDConfig.path}} {{SetDefaultCurrencyUSDConfig.value}}" stepKey="setCurrencyDefaultUSDWebsites"/> <magentoCLI command="config:set --scope={{SetAllowedCurrenciesConfigForUSD.scope}} --scope-code={{SetAllowedCurrenciesConfigForUSD.scope_code}} {{SetAllowedCurrenciesConfigForUSD.path}} {{SetAllowedCurrenciesConfigForUSD.value}}" stepKey="setAllowedCurrencyUSDWebsites"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open created product on Storefront and place for order--> <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencyRatesNavigateMenuTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencyRatesNavigateMenuTest.xml index 4a33d40d2a35f..a5781698deed4 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencyRatesNavigateMenuTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencyRatesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresCurrencyRatesPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencySymbolsNavigateMenuTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencySymbolsNavigateMenuTest.xml index 978917772f2dd..65afd4e2e744a 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencySymbolsNavigateMenuTest.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminStoresCurrencySymbolsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresCurrencySymbolsPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php index b85b735ea9c4f..a65bfa5d77f9e 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Save.php @@ -348,8 +348,14 @@ public function execute() ['customer' => $customer, 'request' => $this->getRequest()] ); - if (isset($customerData['sendemail_store_id'])) { + if (isset($customerData['sendemail_store_id']) && $customerData['sendemail_store_id'] !== false) { $customer->setStoreId($customerData['sendemail_store_id']); + try { + $this->customerAccountManagement->validateCustomerStoreIdByWebsiteId($customer); + } catch (LocalizedException $exception) { + throw new LocalizedException(__("The Store View selected for sending Welcome email from". + " is not related to the customer's associated website.")); + } } // Save customer diff --git a/app/code/Magento/Customer/CustomerData/SectionConfigConverter.php b/app/code/Magento/Customer/CustomerData/SectionConfigConverter.php index 5f4bbb03d3936..c9a93c708e348 100644 --- a/app/code/Magento/Customer/CustomerData/SectionConfigConverter.php +++ b/app/code/Magento/Customer/CustomerData/SectionConfigConverter.php @@ -5,6 +5,9 @@ */ namespace Magento\Customer\CustomerData; +/** + * Class that receives xml merged source and process it. + */ class SectionConfigConverter implements \Magento\Framework\Config\ConverterInterface { /** @@ -13,7 +16,7 @@ class SectionConfigConverter implements \Magento\Framework\Config\ConverterInter const INVALIDATE_ALL_SECTIONS_MARKER = '*'; /** - * {@inheritdoc} + * @inheritdoc */ public function convert($source) { @@ -21,10 +24,18 @@ public function convert($source) foreach ($source->getElementsByTagName('action') as $action) { $actionName = strtolower($action->getAttribute('name')); foreach ($action->getElementsByTagName('section') as $section) { - $sections[$actionName][] = strtolower($section->getAttribute('name')); + $sectionName = strtolower($section->getAttribute('name')); + + if ($sectionName === self::INVALIDATE_ALL_SECTIONS_MARKER) { + $sections[$actionName] = []; + $sections[$actionName][] = self::INVALIDATE_ALL_SECTIONS_MARKER; + break; + } else { + $sections[$actionName][] = $sectionName; + } } if (!isset($sections[$actionName])) { - $sections[$actionName] = self::INVALIDATE_ALL_SECTIONS_MARKER; + $sections[$actionName][] = self::INVALIDATE_ALL_SECTIONS_MARKER; } } return [ diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index 2ccaaea45680c..0389a380b36dc 100644 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -7,24 +7,28 @@ use Magento\Customer\Model\Session; use Magento\Customer\Model\Url as CustomerUrl; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\RequestInterface; +use Magento\Framework\Controller\Result\Forward as ResultForward; +use Magento\Framework\Controller\Result\Redirect as ResultRedirect; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; +use Magento\Framework\Stdlib\CookieManagerInterface; +use Magento\Framework\Url\DecoderInterface; use Magento\Framework\Url\HostChecker; use Magento\Framework\UrlInterface; use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Controller\Result\Redirect as ResultRedirect; -use Magento\Framework\Controller\Result\Forward as ResultForward; -use Magento\Framework\Url\DecoderInterface; -use Magento\Framework\App\ObjectManager; -use Magento\Framework\Stdlib\CookieManagerInterface; /** + * Account Redirect * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Redirect { + /** URL to redirect user on successful login or registration */ const LOGIN_REDIRECT_URL = 'login_redirect'; @@ -64,10 +68,15 @@ class Redirect */ protected $resultFactory; + /** + * @var CookieMetadataFactory + */ + protected $cookieMetadataFactory; + /** * @var CookieManagerInterface */ - protected $cookieManager; + private $cookieManager; /** * @var HostChecker @@ -80,6 +89,7 @@ class Redirect private $session; /** + * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @param RequestInterface $request * @param Session $customerSession * @param ScopeConfigInterface $scopeConfig @@ -88,6 +98,7 @@ class Redirect * @param DecoderInterface $urlDecoder * @param CustomerUrl $customerUrl * @param ResultFactory $resultFactory + * @param CookieMetadataFactory $cookieMetadataFactory * @param HostChecker|null $hostChecker */ public function __construct( @@ -99,6 +110,7 @@ public function __construct( DecoderInterface $urlDecoder, CustomerUrl $customerUrl, ResultFactory $resultFactory, + CookieMetadataFactory $cookieMetadataFactory, HostChecker $hostChecker = null ) { $this->request = $request; @@ -108,6 +120,7 @@ public function __construct( $this->url = $url; $this->urlDecoder = $urlDecoder; $this->customerUrl = $customerUrl; + $this->cookieMetadataFactory = $cookieMetadataFactory; $this->resultFactory = $resultFactory; $this->hostChecker = $hostChecker ?: ObjectManager::getInstance()->get(HostChecker::class); } @@ -238,7 +251,8 @@ private function applyRedirect($url) /** * Get Cookie manager. For release backward compatibility. * - * @deprecated 100.0.10 + * @deprecated 100.0.10 This is legacy method to pass login_redirect cookie + * @see Magento/Checkout/view/frontend/web/js/sidebar.js * @return CookieManagerInterface */ protected function getCookieManager() @@ -252,7 +266,8 @@ protected function getCookieManager() /** * Set cookie manager. For unit tests. * - * @deprecated 100.0.10 + * @deprecated 100.0.10 This is legacy method to pass login_redirect cookie + * @see Magento/Checkout/view/frontend/web/js/sidebar.js * @param object $value * @return void */ @@ -264,6 +279,8 @@ public function setCookieManager($value) /** * Get redirect route from cookie for case of successful login/registration * + * @deprecated 100.0.10 This is legacy method to pass login_redirect cookie + * @see Magento/Checkout/view/frontend/web/js/sidebar.js * @return null|string */ public function getRedirectCookie() @@ -274,21 +291,36 @@ public function getRedirectCookie() /** * Save redirect route to cookie for case of successful login/registration * + * @deprecated 100.0.10 This is legacy method to pass login_redirect cookie + * @see Magento/Checkout/view/frontend/web/js/sidebar.js * @param string $route * @return void */ public function setRedirectCookie($route) { - $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route); + $this->getCookieManager()->setPublicCookie( + self::LOGIN_REDIRECT_URL, + $route, + $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setHttpOnly(true) + ->setDuration(3600) + ->setPath($this->storeManager->getStore()->getStorePath()) + ); } /** * Clear cookie with requested route * + * @deprecated 100.0.10 This is legacy method to pass login_redirect cookie + * @see Magento/Checkout/view/frontend/web/js/sidebar.js * @return void */ public function clearRedirectCookie() { - $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL); + $this->getCookieManager()->deleteCookie( + self::LOGIN_REDIRECT_URL, + $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setPath($this->storeManager->getStore()->getStorePath()) + ); } } diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 55da6a62f0625..122a062beeff8 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -872,7 +872,6 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash if ($customer->getId()) { $customer = $this->customerRepository->get($customer->getEmail()); $websiteId = $customer->getWebsiteId(); - if ($this->isCustomerInStore($websiteId, $customer->getStoreId())) { throw new InputException(__('This customer already exists in this store.')); } @@ -896,13 +895,10 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash $customer->setWebsiteId($websiteId); } + $this->validateCustomerStoreIdByWebsiteId($customer); + // Update 'created_in' value with actual store name if ($customer->getId() === null) { - $websiteId = $customer->getWebsiteId(); - if ($websiteId && !$this->isCustomerInStore($websiteId, $customer->getStoreId())) { - throw new LocalizedException(__('The store view is not in the associated website.')); - } - $storeName = $this->storeManager->getStore($customer->getStoreId())->getName(); $customer->setCreatedIn($storeName); } @@ -1049,10 +1045,10 @@ private function changePasswordForCustomer($customer, $currentPassword, $newPass } $customerEmail = $customer->getEmail(); $this->credentialsValidator->checkPasswordDifferentFromEmail($customerEmail, $newPassword); + $this->checkPasswordStrength($newPassword); $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId()); $customerSecure->setRpToken(null); $customerSecure->setRpTokenCreatedAt(null); - $this->checkPasswordStrength($newPassword); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); $this->destroyCustomerSessions($customer->getId()); $this->disableAddressValidation($customer); @@ -1144,6 +1140,22 @@ public function isCustomerInStore($customerWebsiteId, $storeId) return in_array($storeId, $ids); } + /** + * Validate customer store id by customer website id. + * + * @param CustomerInterface $customer + * @return bool + * @throws LocalizedException + */ + public function validateCustomerStoreIdByWebsiteId(CustomerInterface $customer) + { + if (!$this->isCustomerInStore($customer->getWebsiteId(), $customer->getStoreId())) { + throw new LocalizedException(__('The store view is not in the associated website.')); + } + + return true; + } + /** * Validate the Reset Password Token for a customer. * @@ -1618,6 +1630,7 @@ private function getEmailNotification() */ private function destroyCustomerSessions($customerId) { + $this->sessionManager->regenerateId(); $sessionLifetime = $this->scopeConfig->getValue( \Magento\Framework\Session\Config::XML_PATH_COOKIE_LIFETIME, \Magento\Store\Model\ScopeInterface::SCOPE_STORE diff --git a/app/code/Magento/Customer/Model/Address/Validator/General.php b/app/code/Magento/Customer/Model/Address/Validator/General.php index 7cbb6ef1ab623..4888cd227db48 100644 --- a/app/code/Magento/Customer/Model/Address/Validator/General.php +++ b/app/code/Magento/Customer/Model/Address/Validator/General.php @@ -5,6 +5,7 @@ */ namespace Magento\Customer\Model\Address\Validator; +use Magento\Customer\Api\AddressMetadataInterface; use Magento\Customer\Model\Address\AbstractAddress; use Magento\Customer\Model\Address\ValidatorInterface; @@ -87,6 +88,7 @@ private function checkRequiredFields(AbstractAddress $address) */ private function checkOptionalFields(AbstractAddress $address) { + $this->reloadAddressAttributes($address); $errors = []; if ($this->isTelephoneRequired() && !\Zend_Validate::is($address->getTelephone(), 'NotEmpty') @@ -148,4 +150,17 @@ private function isFaxRequired() { return $this->eavConfig->getAttribute('customer_address', 'fax')->getIsRequired(); } + + /** + * Reload address attributes for the certain store + * + * @param AbstractAddress $address + * @return void + */ + private function reloadAddressAttributes(AbstractAddress $address): void + { + $attributeSetId = $address->getAttributeSetId() ?: AddressMetadataInterface::ATTRIBUTE_SET_ID_ADDRESS; + $address->setData('attribute_set_id', $attributeSetId); + $this->eavConfig->getEntityAttributes(AddressMetadataInterface::ENTITY_TYPE_ADDRESS, $address); + } } diff --git a/app/code/Magento/Customer/Model/CustomerRegistry.php b/app/code/Magento/Customer/Model/CustomerRegistry.php index b89cce8957487..d68904f6d1645 100644 --- a/app/code/Magento/Customer/Model/CustomerRegistry.php +++ b/app/code/Magento/Customer/Model/CustomerRegistry.php @@ -195,7 +195,7 @@ public function removeByEmail($customerEmail, $websiteId = null) $websiteId = $this->storeManager->getStore()->getWebsiteId(); } $emailKey = $this->getEmailKey($customerEmail, $websiteId); - if ($emailKey) { + if (isset($this->customerRegistryByEmail[$emailKey])) { /** @var Customer $customer */ $customer = $this->customerRegistryByEmail[$emailKey]; unset($this->customerRegistryByEmail[$emailKey]); diff --git a/app/code/Magento/Customer/Model/Indexer/Processor.php b/app/code/Magento/Customer/Model/Indexer/Processor.php new file mode 100644 index 0000000000000..6b44b674b405a --- /dev/null +++ b/app/code/Magento/Customer/Model/Indexer/Processor.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Customer\Model\Indexer; + +use Magento\Customer\Model\Customer; + +/** + * Customer indexer + */ +class Processor extends \Magento\Framework\Indexer\AbstractProcessor +{ + const INDEXER_ID = Customer::CUSTOMER_GRID_INDEXER_ID; +} diff --git a/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAddressAttributesSortOrder.php b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAddressAttributesSortOrder.php new file mode 100644 index 0000000000000..b35a21751ebea --- /dev/null +++ b/app/code/Magento/Customer/Setup/Patch/Data/UpdateCustomerAddressAttributesSortOrder.php @@ -0,0 +1,106 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Setup\Patch\Data; + +use Magento\Customer\Setup\CustomerSetup; +use Magento\Customer\Setup\CustomerSetupFactory; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\Patch\DataPatchInterface; + +/** + * Update Customer Address Attributes to be displayed in following order: country, region, city, postcode + */ +class UpdateCustomerAddressAttributesSortOrder implements DataPatchInterface +{ + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * @var CustomerSetupFactory + */ + private $customerSetupFactory; + + /** + * UpdateCustomerAddressAttributesSortOrder constructor. + * @param ModuleDataSetupInterface $moduleDataSetup + * @param CustomerSetupFactory $customerSetupFactory + */ + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + CustomerSetupFactory $customerSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; + $this->customerSetupFactory = $customerSetupFactory; + } + + /** + * @inheritDoc + */ + public function apply() + { + /** @var CustomerSetup $customerSetup */ + $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]); + $this->updateCustomerAddressAttributesSortOrder($customerSetup); + + return $this; + } + + /** + * @inheritDoc + */ + public function getAliases() + { + return []; + } + + /** + * @inheritDoc + */ + public static function getDependencies() + { + return [ + DefaultCustomerGroupsAndAttributes::class, + ]; + } + + /** + * Update customer address attributes sort order + * + * @param CustomerSetup $customerSetup + * + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + private function updateCustomerAddressAttributesSortOrder($customerSetup) + { + $entityAttributes = [ + 'customer_address' => [ + 'country_id' => [ + 'sort_order' => 80, + 'position' => 80 + ], + 'region' => [ + 'sort_order' => 90, + 'position' => 90 + ], + 'region_id' => [ + 'sort_order' => 90, + 'position' => 90 + ], + 'city' => [ + 'sort_order' => 100, + 'position' => 100 + ], + ], + ]; + + $customerSetup->upgradeAttributes($entityAttributes); + } +} diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminClearCustomersFiltersActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminClearCustomersFiltersActionGroup.xml new file mode 100644 index 0000000000000..3ca41bb014d47 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminClearCustomersFiltersActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AdminClearCustomersFiltersActionGroup"> + <annotations> + <description>Goes to the Admin Customers grid page. Clicks on 'Clear Filters'.</description> + </annotations> + + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="amOnCustomersPage"/> + <waitForPageLoad stepKey="WaitForPageToLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebSiteAndGroupActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebSiteAndGroupActionGroup.xml new file mode 100644 index 0000000000000..fb4c1980fe975 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebSiteAndGroupActionGroup.xml @@ -0,0 +1,34 @@ +<?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="AdminCreateCustomerWithWebSiteAndGroupActionGroup"> + <annotations> + <description>Goes to the Customer grid page. Click on 'Add New Customer'. Fills provided Customer Data. Fill provided Customer Address data. Assigns Product to Website and Store View. Clicks on Save.</description> + </annotations> + <arguments> + <argument name="customerData" defaultValue="Simple_US_Customer"/> + <argument name="website" type="string" defaultValue="{{_defaultWebsite.name}}"/> + <argument name="storeView" type="string" defaultValue="{{_defaultStore.name}}"/> + </arguments> + + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="goToCustomersPage"/> + <click stepKey="addNewCustomer" selector="{{AdminCustomerGridMainActionsSection.addNewCustomer}}"/> + <selectOption stepKey="selectWebSite" selector="{{AdminCustomerAccountInformationSection.associateToWebsite}}" userInput="{{website}}"/> + <selectOption selector="{{AdminCustomerAccountInformationSection.group}}" userInput="{{customerData.group}}" stepKey="selectCustomerGroup"/> + <fillField stepKey="FillFirstName" selector="{{AdminCustomerAccountInformationSection.firstName}}" userInput="{{customerData.firstname}}"/> + <fillField stepKey="FillLastName" selector="{{AdminCustomerAccountInformationSection.lastName}}" userInput="{{customerData.lastname}}"/> + <fillField stepKey="FillEmail" selector="{{AdminCustomerAccountInformationSection.email}}" userInput="{{customerData.email}}"/> + <selectOption stepKey="selectStoreView" selector="{{AdminCustomerAccountInformationSection.storeView}}" userInput="{{storeView}}"/> + <waitForElement selector="{{AdminCustomerAccountInformationSection.storeView}}" stepKey="waitForCustomerStoreViewExpand"/> + <click stepKey="save" selector="{{AdminCustomerAccountInformationSection.saveCustomer}}"/> + <waitForPageLoad stepKey="waitForCustomersPage"/> + <see stepKey="seeSuccessMessage" userInput="You saved the customer."/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml index 9741d4e4133bf..5757f79a7ac61 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminCreateCustomerWithWebsiteAndStoreViewActionGroup.xml @@ -47,28 +47,4 @@ <click stepKey="saveAddress" selector="{{AdminCustomerAddressesSection.saveAddress}}"/> <waitForPageLoad stepKey="waitForAddressSave"/> </actionGroup> - - <actionGroup name="AdminCreateCustomerWithWebSiteAndGroup"> - <annotations> - <description>Goes to the Customer grid page. Click on 'Add New Customer'. Fills provided Customer Data. Fill provided Customer Address data. Assigns Product to Website and Store View. Clicks on Save.</description> - </annotations> - <arguments> - <argument name="customerData" defaultValue="Simple_US_Customer"/> - <argument name="website" type="string" defaultValue="{{_defaultWebsite.name}}"/> - <argument name="storeView" type="string" defaultValue="{{_defaultStore.name}}"/> - </arguments> - - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="goToCustomersPage"/> - <click stepKey="addNewCustomer" selector="{{AdminCustomerGridMainActionsSection.addNewCustomer}}"/> - <selectOption stepKey="selectWebSite" selector="{{AdminCustomerAccountInformationSection.associateToWebsite}}" userInput="{{website}}"/> - <selectOption selector="{{AdminCustomerAccountInformationSection.group}}" userInput="{{customerData.group}}" stepKey="selectCustomerGroup"/> - <fillField stepKey="FillFirstName" selector="{{AdminCustomerAccountInformationSection.firstName}}" userInput="{{customerData.firstname}}"/> - <fillField stepKey="FillLastName" selector="{{AdminCustomerAccountInformationSection.lastName}}" userInput="{{customerData.lastname}}"/> - <fillField stepKey="FillEmail" selector="{{AdminCustomerAccountInformationSection.email}}" userInput="{{customerData.email}}"/> - <selectOption stepKey="selectStoreView" selector="{{AdminCustomerAccountInformationSection.storeView}}" userInput="{{storeView}}"/> - <waitForElement selector="{{AdminCustomerAccountInformationSection.storeView}}" stepKey="waitForCustomerStoreViewExpand"/> - <click stepKey="save" selector="{{AdminCustomerAccountInformationSection.saveCustomer}}"/> - <waitForPageLoad stepKey="waitForCustomersPage"/> - <see stepKey="seeSuccessMessage" userInput="You saved the customer."/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressNoZipNoStateActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressNoZipNoStateActionGroup.xml index 4c3660ac605a6..2ccef6f72e23f 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressNoZipNoStateActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressNoZipNoStateActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminEditCustomerAddressNoZipNoState" extends="AdminEditCustomerAddressesFrom"> + <actionGroup name="AdminEditCustomerAddressNoZipNoStateActionGroup" extends="AdminEditCustomerAddressesFromActionGroup"> <annotations> <description>EXTENDS: AdminEditCustomerAddressesFrom. Removes 'selectState' and 'fillZipCode'. Clicks on 'Set Default' for Billing/Shipping.</description> </annotations> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup.xml index 3551375c0e76b..e39800f8d9dd9 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup.xml @@ -8,7 +8,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminEditCustomerAddressSetDefaultShippingAndBilling" extends="AdminEditCustomerAddressesFrom"> + <actionGroup name="AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup" extends="AdminEditCustomerAddressesFromActionGroup"> <annotations> <description>EXTENDS: AdminEditCustomerAddressesFrom. Removes 'selectState' and 'fillZipCode'.</description> </annotations> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml index 8ac4779de7a9a..c2b41251c05b1 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AdminEditCustomerAddressesFromActionGroup.xml @@ -9,7 +9,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <!-- Same as "EditCustomerAddressesFromAdminActionGroup" but taking country and state from input "customerAddress" --> - <actionGroup name="AdminEditCustomerAddressesFrom"> + <actionGroup name="AdminEditCustomerAddressesFromActionGroup"> <annotations> <description>Adds the provided Address to a Customer from the Admin Customers creation/edit page.</description> </annotations> @@ -34,38 +34,4 @@ <click selector="{{AdminEditCustomerAddressesSection.save}}" stepKey="saveAddress"/> <waitForPageLoad stepKey="waitForAddressSaved"/> </actionGroup> - - <actionGroup name="AdminEditCustomerAddressSetDefaultShippingAndBilling" extends="AdminEditCustomerAddressesFrom"> - <annotations> - <description>EXTENDS: AdminEditCustomerAddressesFrom. Clicks on 'Set Default' for Billing/Shipping.</description> - </annotations> - - <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> - <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> - </actionGroup> - - <actionGroup name="AdminEditCustomerAddressNoZipNoState" extends="AdminEditCustomerAddressesFrom"> - <annotations> - <description>EXTENDS: AdminEditCustomerAddressesFrom. Removes 'selectState' and 'fillZipCode'. Clicks on 'Set Default' for Billing/Shipping.</description> - </annotations> - - <remove keyForRemoval="selectState"/> - <remove keyForRemoval="fillZipCode"/> - <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> - <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> - </actionGroup> - - <actionGroup name="SelectDropdownCustomerAddressAttributeValueActionGroup"> - <annotations> - <description>Selects the provided Option in the provided Customer Address Attribute drop down menu. Clicks on Save.</description> - </annotations> - <arguments> - <argument name="customerAddressAttribute"/> - <argument name="optionValue" type="string"/> - </arguments> - - <selectOption selector="{{AdminEditCustomerAddressesSection.dropDownAttribute(customerAddressAttribute.code)}}" userInput="{{optionValue}}" stepKey="selectOptionValue"/> - <click selector="{{AdminEditCustomerAddressesSection.save}}" stepKey="saveAddress"/> - <waitForPageLoad stepKey="waitForAddressSaved"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertSignedUpNewsletterActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertSignedUpNewsletterActionGroup.xml new file mode 100644 index 0000000000000..deabec7d671d6 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertSignedUpNewsletterActionGroup.xml @@ -0,0 +1,26 @@ +<?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="AssertSignedUpNewsletterActionGroup"> + <annotations> + <description>Validates that the provided Customer details are present and correct on the Storefront Customer Dashboard page.</description> + </annotations> + <arguments> + <argument name="customer" defaultValue="CustomerEntityOne"/> + <argument name="storeName" defaultValue="Main Website" type="string"/> + </arguments> + + <see stepKey="successMessage" userInput="Thank you for registering with {{storeName}} Store." selector="{{AdminCustomerMessagesSection.successMessage}}"/> + <see stepKey="seeFirstName" userInput="{{customer.firstname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> + <see stepKey="seeLastName" userInput="{{customer.lastname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> + <see stepKey="seeEmail" userInput="{{customer.email}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> + <seeInCurrentUrl url="{{StorefrontCustomerDashboardPage.url}}" stepKey="seeAssertInCurrentUrl"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml new file mode 100644 index 0000000000000..eb66cafe43dd3 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml @@ -0,0 +1,20 @@ +<?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="AssertStorefrontDefaultWelcomeMessageActionGroup"> + <annotations> + <description>Validates that the Welcome message is present and correct and not you link absent.</description> + </annotations> + + <waitForElementVisible selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="waitDefaultMessage"/> + <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="verifyDefaultMessage"/> + <dontSeeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkAbsenceLinkNotYou"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerActionGroup.xml index 81b8cabaa51ef..62f4c87545c6f 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerActionGroup.xml @@ -30,29 +30,4 @@ <waitForElementVisible stepKey="waitForSuccessfullyDeletedMessage" selector="{{CustomersPageSection.deletedSuccessMessage}}" time="10"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskDisappear"/> </actionGroup> - - <actionGroup name="DeleteCustomerByEmailActionGroup"> - <annotations> - <description>Goes to the Admin Customers grid page. Deletes a Customer based on the provided Email Address.</description> - </annotations> - <arguments> - <argument name="email" type="string"/> - </arguments> - - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> - <waitForPageLoad stepKey="waitForAdminCustomerPageLoad"/> - <click selector="{{AdminCustomerFiltersSection.filtersButton}}" stepKey="clickFilterButton"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="cleanFiltersIfTheySet"/> - <waitForPageLoad stepKey="waitForClearFilters"/> - <fillField selector="{{AdminCustomerFiltersSection.emailInput}}" userInput="{{email}}" stepKey="filterEmail"/> - <click selector="{{AdminCustomerFiltersSection.apply}}" stepKey="applyFilter"/> - <waitForPageLoad stepKey="waitForPageToLoad"/> - <click selector="{{AdminCustomerGridSection.selectFirstRow}}" stepKey="clickOnEditButton1"/> - <click selector="{{CustomersPageSection.actions}}" stepKey="clickActionsDropdown"/> - <click selector="{{CustomersPageSection.delete}}" stepKey="clickDelete"/> - <waitForElementVisible selector="{{CustomersPageSection.ok}}" stepKey="waitForOkToVisible"/> - <click selector="{{CustomersPageSection.ok}}" stepKey="clickOkConfirmationButton"/> - <waitForElementVisible stepKey="waitForSuccessfullyDeletedMessage" selector="{{CustomersPageSection.deletedSuccessMessage}}" time="10"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskDisappear"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerByEmailActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerByEmailActionGroup.xml new file mode 100644 index 0000000000000..5920596633f76 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerByEmailActionGroup.xml @@ -0,0 +1,34 @@ +<?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="DeleteCustomerByEmailActionGroup"> + <annotations> + <description>Goes to the Admin Customers grid page. Deletes a Customer based on the provided Email Address.</description> + </annotations> + <arguments> + <argument name="email" type="string"/> + </arguments> + + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> + <waitForPageLoad stepKey="waitForAdminCustomerPageLoad"/> + <click selector="{{AdminCustomerFiltersSection.filtersButton}}" stepKey="clickFilterButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="cleanFiltersIfTheySet"/> + <waitForPageLoad stepKey="waitForClearFilters"/> + <fillField selector="{{AdminCustomerFiltersSection.emailInput}}" userInput="{{email}}" stepKey="filterEmail"/> + <click selector="{{AdminCustomerFiltersSection.apply}}" stepKey="applyFilter"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <click selector="{{AdminCustomerGridSection.selectFirstRow}}" stepKey="clickOnEditButton1"/> + <click selector="{{CustomersPageSection.actions}}" stepKey="clickActionsDropdown"/> + <click selector="{{CustomersPageSection.delete}}" stepKey="clickDelete"/> + <waitForElementVisible selector="{{CustomersPageSection.ok}}" stepKey="waitForOkToVisible"/> + <click selector="{{CustomersPageSection.ok}}" stepKey="clickOkConfirmationButton"/> + <waitForElementVisible stepKey="waitForSuccessfullyDeletedMessage" selector="{{CustomersPageSection.deletedSuccessMessage}}" time="30"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerFromAdminActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerFromAdminActionGroup.xml new file mode 100644 index 0000000000000..04083f688b75d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/DeleteCustomerFromAdminActionGroup.xml @@ -0,0 +1,31 @@ +<?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="DeleteCustomerFromAdminActionGroup"> + <annotations> + <description>Goes to the Admin Customers grid page. Deletes the provided Customer from the grid. Validates that the Success message is present and correct.</description> + </annotations> + <arguments> + <argument name="customer" defaultValue="CustomerEntityOne"/> + </arguments> + + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> + <fillField selector="{{AdminDataGridHeaderSection.search}}" userInput="{{customer.email}}" stepKey="fillSearch"/> + <click selector="{{AdminDataGridHeaderSection.submitSearch}}" stepKey="clickSubmit"/> + <waitForAjaxLoad stepKey="waitForLoadAjax"/> + <click selector="{{AdminCustomerGridMainActionsSection.multicheck}}" stepKey="selectAll"/> + <click selector="{{AdminCustomerGridMainActionsSection.actions}}" stepKey="clickActions"/> + <click selector="{{AdminCustomerGridMainActionsSection.delete}}" stepKey="clickDelete"/> + <waitForAjaxLoad stepKey="waitForLoadConfirmation"/> + <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDelete"/> + <see selector="{{AdminMessagesSection.success}}" userInput="A total of 1 record(s) were deleted" stepKey="seeSuccess"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoActionGroup.xml new file mode 100644 index 0000000000000..c72010fe5c3bf --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoActionGroup.xml @@ -0,0 +1,33 @@ +<?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="EnterCustomerAddressInfoActionGroup"> + <annotations> + <description>Fills in the provided Customer details (First/Last Name, Company, Phone # and Address) on the Admin Customer creation/edit page. Clicks on the Save button.</description> + </annotations> + <arguments> + <argument name="Address"/> + </arguments> + + <amOnPage url="customer/address/new/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPage"/> + <fillField stepKey="fillFirstName" selector="{{StorefrontCustomerAddressSection.firstName}}" userInput="{{Address.firstname}}"/> + <fillField stepKey="fillLastName" selector="{{StorefrontCustomerAddressSection.lastName}}" userInput="{{Address.lastname}}"/> + <fillField stepKey="fillCompany" selector="{{StorefrontCustomerAddressSection.company}}" userInput="{{Address.company}}"/> + <fillField stepKey="fillPhoneNumber" selector="{{StorefrontCustomerAddressSection.phoneNumber}}" userInput="{{Address.telephone}}"/> + <fillField stepKey="fillStreetAddress1" selector="{{StorefrontCustomerAddressSection.streetAddress1}}" userInput="{{Address.street[0]}}"/> + <fillField stepKey="fillStreetAddress2" selector="{{StorefrontCustomerAddressSection.streetAddress2}}" userInput="{{Address.street[1]}}"/> + <fillField stepKey="fillCityName" selector="{{StorefrontCustomerAddressSection.city}}" userInput="{{Address.city}}"/> + <selectOption stepKey="selectCounty" selector="{{StorefrontCustomerAddressSection.country}}" userInput="{{Address.country_id}}"/> + <selectOption stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvince}}" userInput="{{Address.state}}"/> + <fillField stepKey="fillZip" selector="{{StorefrontCustomerAddressSection.zip}}" userInput="{{Address.postcode}}"/> + <click stepKey="saveAddress" selector="{{StorefrontCustomerAddressSection.saveAddress}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoFillStateActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoFillStateActionGroup.xml new file mode 100644 index 0000000000000..891b578e54e6b --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/EnterCustomerAddressInfoFillStateActionGroup.xml @@ -0,0 +1,18 @@ +<?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="EnterCustomerAddressInfoFillStateActionGroup" extends="EnterCustomerAddressInfoActionGroup"> + <annotations> + <description>EXTENDS: EnterCustomerAddressInfo. Fills the State field.</description> + </annotations> + + <fillField stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvinceFill}}" userInput="{{Address.state}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerAddressFromAdminActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerAddressFromAdminActionGroup.xml new file mode 100644 index 0000000000000..86ac1dc650bbc --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerAddressFromAdminActionGroup.xml @@ -0,0 +1,32 @@ +<?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="OpenEditCustomerAddressFromAdminActionGroup"> + <annotations> + <description>Filters the Admin Customers Addresses based on the provided Address. Clicks on Edit.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <click selector="{{AdminCustomerAccountInformationSection.addressesButton}}" stepKey="openAddressesTab"/> + <waitForElementVisible selector="{{AdminCustomerAddressFiltersSection.filtersButton}}" stepKey="waitForComponentLoad"/> + <click selector="{{AdminCustomerAddressFiltersSection.filtersButton}}" stepKey="openAddressesFilter"/> + <fillField userInput="{{address.firstname}}" selector="{{AdminCustomerAddressFiltersSection.firstnameInput}}" stepKey="fillFirstname"/> + <fillField userInput="{{address.lastname}}" selector="{{AdminCustomerAddressFiltersSection.lastnameInput}}" stepKey="fillLastname"/> + <fillField userInput="{{address.telephone}}" selector="{{AdminCustomerAddressFiltersSection.telephoneInput}}" stepKey="fillCountry"/> + <fillField userInput="{{address.postcode}}" selector="{{AdminCustomerAddressFiltersSection.postcodeInput}}" stepKey="fillPostcode"/> + <click selector="{{AdminCustomerAddressFiltersSection.applyFilter}}" stepKey="applyAddressesFilter"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> + <click selector="{{AdminCustomerAddressGridSection.firstRowSelectActionLink}}" stepKey="clickAction"/> + <click selector="{{AdminCustomerAddressGridSection.firstRowEditActionLink}}" stepKey="clickEdit"/> + <waitForPageLoad stepKey="waitForModalWindow"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml index e338d1ae4bbd0..c9d5375d9b3d7 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/OpenEditCustomerFromAdminActionGroup.xml @@ -26,57 +26,4 @@ <click selector="{{AdminCustomerGridSection.firstRowEditLink}}" stepKey="clickEdit"/> <waitForPageLoad stepKey="waitForPageLoad3"/> </actionGroup> - - <actionGroup name="OpenEditCustomerAddressFromAdminActionGroup"> - <annotations> - <description>Filters the Admin Customers Addresses based on the provided Address. Clicks on Edit.</description> - </annotations> - <arguments> - <argument name="address"/> - </arguments> - - <click selector="{{AdminCustomerAccountInformationSection.addressesButton}}" stepKey="openAddressesTab"/> - <waitForElementVisible selector="{{AdminCustomerAddressFiltersSection.filtersButton}}" stepKey="waitForComponentLoad"/> - <click selector="{{AdminCustomerAddressFiltersSection.filtersButton}}" stepKey="openAddressesFilter"/> - <fillField userInput="{{address.firstname}}" selector="{{AdminCustomerAddressFiltersSection.firstnameInput}}" stepKey="fillFirstname"/> - <fillField userInput="{{address.lastname}}" selector="{{AdminCustomerAddressFiltersSection.lastnameInput}}" stepKey="fillLastname"/> - <fillField userInput="{{address.telephone}}" selector="{{AdminCustomerAddressFiltersSection.telephoneInput}}" stepKey="fillCountry"/> - <fillField userInput="{{address.postcode}}" selector="{{AdminCustomerAddressFiltersSection.postcodeInput}}" stepKey="fillPostcode"/> - <click selector="{{AdminCustomerAddressFiltersSection.applyFilter}}" stepKey="applyAddressesFilter"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> - <click selector="{{AdminCustomerAddressGridSection.firstRowSelectActionLink}}" stepKey="clickAction"/> - <click selector="{{AdminCustomerAddressGridSection.firstRowEditActionLink}}" stepKey="clickEdit"/> - <waitForPageLoad stepKey="waitForModalWindow"/> - </actionGroup> - - <actionGroup name="DeleteCustomerFromAdminActionGroup"> - <annotations> - <description>Goes to the Admin Customers grid page. Deletes the provided Customer from the grid. Validates that the Success message is present and correct.</description> - </annotations> - <arguments> - <argument name="customer" defaultValue="CustomerEntityOne"/> - </arguments> - - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> - <fillField selector="{{AdminDataGridHeaderSection.search}}" userInput="{{customer.email}}" stepKey="fillSearch"/> - <click selector="{{AdminDataGridHeaderSection.submitSearch}}" stepKey="clickSubmit"/> - <waitForAjaxLoad stepKey="waitForLoadAjax"/> - <click selector="{{AdminCustomerGridMainActionsSection.multicheck}}" stepKey="selectAll"/> - <click selector="{{AdminCustomerGridMainActionsSection.actions}}" stepKey="clickActions"/> - <click selector="{{AdminCustomerGridMainActionsSection.delete}}" stepKey="clickDelete"/> - <waitForAjaxLoad stepKey="waitForLoadConfirmation"/> - <click selector="{{AdminConfirmationModalSection.ok}}" stepKey="confirmDelete"/> - <see selector="{{AdminMessagesSection.success}}" userInput="A total of 1 record(s) were deleted" stepKey="seeSuccess"/> - </actionGroup> - - <actionGroup name="AdminClearCustomersFiltersActionGroup"> - <annotations> - <description>Goes to the Admin Customers grid page. Clicks on 'Clear Filters'.</description> - </annotations> - - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="amOnCustomersPage"/> - <waitForPageLoad stepKey="WaitForPageToLoad"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickOnButtonToRemoveFiltersIfPresent"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SaveRegistrationFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SaveRegistrationFormActionGroup.xml new file mode 100644 index 0000000000000..babef0fdd60d9 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SaveRegistrationFormActionGroup.xml @@ -0,0 +1,15 @@ +<?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="SaveRegistrationFormActionGroup"> + <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> + <waitForPageLoad stepKey="waitForCreateAccountButtonToLoad" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SelectDropdownCustomerAddressAttributeValueActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SelectDropdownCustomerAddressAttributeValueActionGroup.xml new file mode 100644 index 0000000000000..5d0fb2e7b5c8d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SelectDropdownCustomerAddressAttributeValueActionGroup.xml @@ -0,0 +1,24 @@ +<?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="SelectDropdownCustomerAddressAttributeValueActionGroup"> + <annotations> + <description>Selects the provided Option in the provided Customer Address Attribute drop down menu. Clicks on Save.</description> + </annotations> + <arguments> + <argument name="customerAddressAttribute"/> + <argument name="optionValue" type="string"/> + </arguments> + + <selectOption selector="{{AdminEditCustomerAddressesSection.dropDownAttribute(customerAddressAttribute.code)}}" userInput="{{optionValue}}" stepKey="selectOptionValue"/> + <click selector="{{AdminEditCustomerAddressesSection.save}}" stepKey="saveAddress"/> + <waitForPageLoad stepKey="waitForAddressSaved"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewCustomerStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewCustomerStorefrontActionGroup.xml new file mode 100644 index 0000000000000..f994bafda73e0 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewCustomerStorefrontActionGroup.xml @@ -0,0 +1,19 @@ +<?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="SignUpNewCustomerStorefrontActionGroup" extends="SignUpNewUserFromStorefrontActionGroup"> + <annotations> + <description>EXTENDS: SignUpNewUserFromStorefrontActionGroup. Adds a waitForPageLoad action to the Action Group. Removes the action for 'seeThankYouMessage'.</description> + </annotations> + + <waitForPageLoad stepKey="waitForRegistered" after="clickCreateAccountButton"/> + <remove keyForRemoval="seeThankYouMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index 4260417b46fd0..56afa8854ce0d 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -17,6 +17,7 @@ </arguments> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <waitForElementVisible selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}" stepKey="waitForCreateAccountLink"/> <click stepKey="clickOnCreateAccountLink" selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}"/> <fillField stepKey="fillFirstName" userInput="{{Customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}"/> <fillField stepKey="fillLastName" userInput="{{Customer.lastname}}" selector="{{StorefrontCustomerCreateFormSection.lastnameField}}"/> @@ -29,193 +30,4 @@ <see stepKey="seeLastName" userInput="{{Customer.lastname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> <see stepKey="seeEmail" userInput="{{Customer.email}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> </actionGroup> - - <actionGroup name="StorefrontCreateCustomerSignedUpNewsletterActionGroup"> - <annotations> - <description>Goes to the Storefront. Clicks on 'Create Account'. Fills in the provided Customer details, including Newsletter Sign-Up. Clicks on 'Create Account' button.</description> - </annotations> - <arguments> - <argument name="customer" defaultValue="CustomerEntityOne"/> - </arguments> - - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <waitForPageLoad stepKey="waitForNavigateToCustomersPageLoad"/> - <click stepKey="clickOnCreateAccountLink" selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}"/> - <fillField stepKey="fillFirstName" userInput="{{customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}"/> - <fillField stepKey="fillLastName" userInput="{{customer.lastname}}" selector="{{StorefrontCustomerCreateFormSection.lastnameField}}"/> - <checkOption selector="{{StorefrontCustomerCreateFormSection.signUpForNewsletter}}" stepKey="checkSignUpForNewsletter"/> - <fillField stepKey="fillEmail" userInput="{{customer.email}}" selector="{{StorefrontCustomerCreateFormSection.emailField}}"/> - <fillField stepKey="fillPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.passwordField}}"/> - <fillField stepKey="fillConfirmPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.confirmPasswordField}}"/> - <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> - <waitForPageLoad stepKey="waitForCreateAccountButtonToLoad"/> - </actionGroup> - - <actionGroup name="StorefrontFillRegistrationFormActionGroup" extends="StorefrontCreateCustomerSignedUpNewsletterActionGroup"> - <remove keyForRemoval="checkSignUpForNewsletter"/> - <remove keyForRemoval="clickCreateAccountButton"/> - <remove keyForRemoval="waitForCreateAccountButtonToLoad"/> - </actionGroup> - - <actionGroup name="SaveRegistrationFormActionGroup"> - <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> - <waitForPageLoad stepKey="waitForCreateAccountButtonToLoad" /> - </actionGroup> - - <actionGroup name="AssertSignedUpNewsletterActionGroup"> - <annotations> - <description>Validates that the provided Customer details are present and correct on the Storefront Customer Dashboard page.</description> - </annotations> - <arguments> - <argument name="customer" defaultValue="CustomerEntityOne"/> - <argument name="storeName" defaultValue="Main Website" type="string"/> - </arguments> - - <see stepKey="successMessage" userInput="Thank you for registering with {{storeName}} Store." selector="{{AdminCustomerMessagesSection.successMessage}}"/> - <see stepKey="seeFirstName" userInput="{{customer.firstname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> - <see stepKey="seeLastName" userInput="{{customer.lastname}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> - <see stepKey="seeEmail" userInput="{{customer.email}}" selector="{{StorefrontCustomerDashboardAccountInformationSection.ContactInformation}}"/> - <seeInCurrentUrl url="{{StorefrontCustomerDashboardPage.url}}" stepKey="seeAssertInCurrentUrl"/> - </actionGroup> - - <actionGroup name="EnterCustomerAddressInfo"> - <annotations> - <description>Fills in the provided Customer details (First/Last Name, Company, Phone # and Address) on the Admin Customer creation/edit page. Clicks on the Save button.</description> - </annotations> - <arguments> - <argument name="Address"/> - </arguments> - - <amOnPage url="customer/address/new/" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPage"/> - <fillField stepKey="fillFirstName" selector="{{StorefrontCustomerAddressSection.firstName}}" userInput="{{Address.firstname}}"/> - <fillField stepKey="fillLastName" selector="{{StorefrontCustomerAddressSection.lastName}}" userInput="{{Address.lastname}}"/> - <fillField stepKey="fillCompany" selector="{{StorefrontCustomerAddressSection.company}}" userInput="{{Address.company}}"/> - <fillField stepKey="fillPhoneNumber" selector="{{StorefrontCustomerAddressSection.phoneNumber}}" userInput="{{Address.telephone}}"/> - <fillField stepKey="fillStreetAddress1" selector="{{StorefrontCustomerAddressSection.streetAddress1}}" userInput="{{Address.street[0]}}"/> - <fillField stepKey="fillStreetAddress2" selector="{{StorefrontCustomerAddressSection.streetAddress2}}" userInput="{{Address.street[1]}}"/> - <fillField stepKey="fillCityName" selector="{{StorefrontCustomerAddressSection.city}}" userInput="{{Address.city}}"/> - <selectOption stepKey="selectCounty" selector="{{StorefrontCustomerAddressSection.country}}" userInput="{{Address.country_id}}"/> - <selectOption stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvince}}" userInput="{{Address.state}}"/> - <fillField stepKey="fillZip" selector="{{StorefrontCustomerAddressSection.zip}}" userInput="{{Address.postcode}}"/> - <click stepKey="saveAddress" selector="{{StorefrontCustomerAddressSection.saveAddress}}"/> - </actionGroup> - - <!-- Fills State Field instead of selecting it--> - <actionGroup name="EnterCustomerAddressInfoFillState" extends="EnterCustomerAddressInfo"> - <annotations> - <description>EXTENDS: EnterCustomerAddressInfo. Fills the State field.</description> - </annotations> - - <fillField stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvinceFill}}" userInput="{{Address.state}}"/> - </actionGroup> - - <actionGroup name="VerifyCustomerBillingAddress"> - <annotations> - <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address is present and correct on the Storefront Customer Dashboard Address section.</description> - </annotations> - <arguments> - <argument name="address"/> - </arguments> - - <amOnPage url="{{StorefrontCustomerAddressesPage.url}}" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPageLoad"/> - - <!--Verify customer default billing address--> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> - </actionGroup> - - <actionGroup name="VerifyCustomerShippingAddress"> - <annotations> - <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address is present and correct.</description> - </annotations> - <arguments> - <argument name="address"/> - </arguments> - - <amOnPage url="{{StorefrontCustomerAddressesPage.url}}" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPageLoad"/> - <!--Verify customer default shipping address--> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> - </actionGroup> - - <actionGroup name="VerifyCustomerBillingAddressWithState"> - <annotations> - <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address, including the State, is present and correct.</description> - </annotations> - <arguments> - <argument name="address"/> - </arguments> - - <amOnPage url="{{StorefrontCustomerAddressesPage.url}}" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPageLoad"/> - - <!--Verify customer default billing address--> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> - </actionGroup> - - <actionGroup name="VerifyCustomerShippingAddressWithState"> - <annotations> - <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address, including the State, is present and correct.</description> - </annotations> - <arguments> - <argument name="address"/> - </arguments> - - <amOnPage url="{{StorefrontCustomerAddressesPage.url}}" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPageLoad"/> - - <!--Verify customer default shipping address--> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> - <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> - </actionGroup> - - <actionGroup name="VerifyCustomerNameOnFrontend"> - <annotations> - <description>Goes to the Storefront Customer Dashboard page. Validates that the Customer First/Last Name is present and correct.</description> - </annotations> - <arguments> - <argument name="customer"/> - </arguments> - - <!--Verify customer name on frontend--> - <amOnPage url="{{StorefrontCustomerEditPage.url}}" stepKey="goToAddressPage"/> - <waitForPageLoad stepKey="waitForAddressPageLoad"/> - <click selector="{{StorefrontCustomerSidebarSection.sidebarCurrentTab('Account Information')}}" stepKey="clickAccountInformationFromSidebarCurrentTab"/> - <waitForPageLoad stepKey="waitForAccountInformationTabToOpen"/> - <seeInField selector="{{StorefrontCustomerAccountInformationSection.firstName}}" userInput="{{customer.firstname}}" stepKey="seeAssertCustomerFirstName"/> - <seeInField selector="{{StorefrontCustomerAccountInformationSection.lastName}}" userInput="{{customer.lastname}}" stepKey="seeAssertCustomerLastName"/> - </actionGroup> - - <actionGroup name="SignUpNewCustomerStorefrontActionGroup" extends="SignUpNewUserFromStorefrontActionGroup"> - <annotations> - <description>EXTENDS: SignUpNewUserFromStorefrontActionGroup. Adds a waitForPageLoad action to the Action Group. Removes the action for 'seeThankYouMessage'.</description> - </annotations> - - <waitForPageLoad stepKey="waitForRegistered" after="clickCreateAccountButton"/> - <remove keyForRemoval="seeThankYouMessage"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerDefaultAddressActionGroup.xml similarity index 57% rename from app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerAddressActionGroup.xml rename to app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerDefaultAddressActionGroup.xml index dc21ce5f52d73..ce26d14bb95f7 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerAddressActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddCustomerDefaultAddressActionGroup.xml @@ -8,28 +8,6 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontAddNewCustomerAddressActionGroup"> - <annotations> - <description>Goes to the Storefront Customer Add New Address page. Fills in the provided Address details. Clicks on Save.</description> - </annotations> - <arguments> - <argument name="Address"/> - </arguments> - - <amOnPage url="customer/address/new/" stepKey="OpenCustomerAddNewAddress"/> - <fillField stepKey="fillFirstName" userInput="{{Address.firstname}}" selector="{{StorefrontCustomerAddressFormSection.firstName}}"/> - <fillField stepKey="fillLastName" userInput="{{Address.lastname}}" selector="{{StorefrontCustomerAddressFormSection.lastName}}"/> - <fillField stepKey="fillCompanyName" userInput="{{Address.company}}" selector="{{StorefrontCustomerAddressFormSection.company}}"/> - <fillField stepKey="fillPhoneNumber" userInput="{{Address.telephone}}" selector="{{StorefrontCustomerAddressFormSection.phoneNumber}}"/> - <fillField stepKey="fillStreetAddress" userInput="{{Address.street[0]}}" selector="{{StorefrontCustomerAddressFormSection.streetAddress}}"/> - <fillField stepKey="fillCity" userInput="{{Address.city}}" selector="{{StorefrontCustomerAddressFormSection.city}}"/> - <selectOption stepKey="selectState" userInput="{{Address.state}}" selector="{{StorefrontCustomerAddressFormSection.state}}"/> - <fillField stepKey="fillZip" userInput="{{Address.postcode}}" selector="{{StorefrontCustomerAddressFormSection.zip}}"/> - <selectOption stepKey="selectCountry" userInput="{{Address.country}}" selector="{{StorefrontCustomerAddressFormSection.country}}"/> - <click stepKey="saveCustomerAddress" selector="{{StorefrontCustomerAddressFormSection.saveAddress}}"/> - <see userInput="You saved the address." stepKey="verifyAddressAdded"/> - </actionGroup> - <actionGroup name="StorefrontAddCustomerDefaultAddressActionGroup"> <annotations> <description>Goes to the Storefront Customer Add New Default Address page. Fills in the provided Address details. Clicks on Save.</description> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddNewCustomerAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddNewCustomerAddressActionGroup.xml new file mode 100644 index 0000000000000..358930070bc1b --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAddNewCustomerAddressActionGroup.xml @@ -0,0 +1,32 @@ +<?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="StorefrontAddNewCustomerAddressActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Add New Address page. Fills in the provided Address details. Clicks on Save.</description> + </annotations> + <arguments> + <argument name="Address"/> + </arguments> + + <amOnPage url="customer/address/new/" stepKey="OpenCustomerAddNewAddress"/> + <fillField stepKey="fillFirstName" userInput="{{Address.firstname}}" selector="{{StorefrontCustomerAddressFormSection.firstName}}"/> + <fillField stepKey="fillLastName" userInput="{{Address.lastname}}" selector="{{StorefrontCustomerAddressFormSection.lastName}}"/> + <fillField stepKey="fillCompanyName" userInput="{{Address.company}}" selector="{{StorefrontCustomerAddressFormSection.company}}"/> + <fillField stepKey="fillPhoneNumber" userInput="{{Address.telephone}}" selector="{{StorefrontCustomerAddressFormSection.phoneNumber}}"/> + <fillField stepKey="fillStreetAddress" userInput="{{Address.street[0]}}" selector="{{StorefrontCustomerAddressFormSection.streetAddress}}"/> + <fillField stepKey="fillCity" userInput="{{Address.city}}" selector="{{StorefrontCustomerAddressFormSection.city}}"/> + <selectOption stepKey="selectState" userInput="{{Address.state}}" selector="{{StorefrontCustomerAddressFormSection.state}}"/> + <fillField stepKey="fillZip" userInput="{{Address.postcode}}" selector="{{StorefrontCustomerAddressFormSection.zip}}"/> + <selectOption stepKey="selectCountry" userInput="{{Address.country}}" selector="{{StorefrontCustomerAddressFormSection.country}}"/> + <click stepKey="saveCustomerAddress" selector="{{StorefrontCustomerAddressFormSection.saveAddress}}"/> + <see userInput="You saved the address." stepKey="verifyAddressAdded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCreateCustomerSignedUpNewsletterActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCreateCustomerSignedUpNewsletterActionGroup.xml new file mode 100644 index 0000000000000..22a90fca78cb2 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCreateCustomerSignedUpNewsletterActionGroup.xml @@ -0,0 +1,31 @@ +<?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="StorefrontCreateCustomerSignedUpNewsletterActionGroup"> + <annotations> + <description>Goes to the Storefront. Clicks on 'Create Account'. Fills in the provided Customer details, including Newsletter Sign-Up. Clicks on 'Create Account' button.</description> + </annotations> + <arguments> + <argument name="customer" defaultValue="CustomerEntityOne"/> + </arguments> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <waitForPageLoad stepKey="waitForNavigateToCustomersPageLoad"/> + <click stepKey="clickOnCreateAccountLink" selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}"/> + <fillField stepKey="fillFirstName" userInput="{{customer.firstname}}" selector="{{StorefrontCustomerCreateFormSection.firstnameField}}"/> + <fillField stepKey="fillLastName" userInput="{{customer.lastname}}" selector="{{StorefrontCustomerCreateFormSection.lastnameField}}"/> + <checkOption selector="{{StorefrontCustomerCreateFormSection.signUpForNewsletter}}" stepKey="checkSignUpForNewsletter"/> + <fillField stepKey="fillEmail" userInput="{{customer.email}}" selector="{{StorefrontCustomerCreateFormSection.emailField}}"/> + <fillField stepKey="fillPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.passwordField}}"/> + <fillField stepKey="fillConfirmPassword" userInput="{{customer.password}}" selector="{{StorefrontCustomerCreateFormSection.confirmPasswordField}}"/> + <click stepKey="clickCreateAccountButton" selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}"/> + <waitForPageLoad stepKey="waitForCreateAccountButtonToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml index ed221350918a0..bbe5fcbbf4038 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml @@ -16,15 +16,4 @@ <amOnPage url="{{StorefrontCustomerLogoutPage.url}}" stepKey="storefrontSignOut"/> <waitForPageLoad stepKey="waitForSignOut"/> </actionGroup> - - <actionGroup name="StorefrontSignOutActionGroup"> - <annotations> - <description>Clicks on Customer Account. Clicks on 'Sign-Out'. Validates that the success message is present and correct. PLEASE NOTE: The Success Message is hardcoded.</description> - </annotations> - - <click selector="{{StoreFrontSignOutSection.customerAccount}}" stepKey="clickCustomerButton"/> - <click selector="{{StoreFrontSignOutSection.signOut}}" stepKey="clickToSignOut"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see userInput="You are signed out" stepKey="signOut"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillRegistrationFormActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillRegistrationFormActionGroup.xml new file mode 100644 index 0000000000000..984d4f437aeb0 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillRegistrationFormActionGroup.xml @@ -0,0 +1,16 @@ +<?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="StorefrontFillRegistrationFormActionGroup" extends="StorefrontCreateCustomerSignedUpNewsletterActionGroup"> + <remove keyForRemoval="checkSignUpForNewsletter"/> + <remove keyForRemoval="clickCreateAccountButton"/> + <remove keyForRemoval="waitForCreateAccountButtonToLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml index 31a988ac9da0d..b013b1db1c8e7 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageActionGroup.xml @@ -16,15 +16,4 @@ <amOnPage url="{{StorefrontCustomerCreatePage.url}}" stepKey="goToCustomerAccountCreatePage"/> <waitForPageLoad stepKey="waitForPageLoaded"/> </actionGroup> - - <actionGroup name="StorefrontOpenCustomerAccountCreatePageUsingStoreCodeInUrlActionGroup"> - <annotations> - <description>Goes to the Storefront Customer Create page using Store code in URL option.</description> - </annotations> - <arguments> - <argument name="storeView" type="string" defaultValue="{{customStore.code}}"/> - </arguments> - - <amOnPage url="{{StorefrontStoreHomePage.url(storeView)}}{{StorefrontCustomerCreatePage.url}}" stepKey="goToCustomerAccountCreatePage"/> - </actionGroup> </actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageUsingStoreCodeInUrlActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageUsingStoreCodeInUrlActionGroup.xml new file mode 100644 index 0000000000000..f095927c5be1b --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenCustomerAccountCreatePageUsingStoreCodeInUrlActionGroup.xml @@ -0,0 +1,21 @@ +<?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="StorefrontOpenCustomerAccountCreatePageUsingStoreCodeInUrlActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Create page using Store code in URL option.</description> + </annotations> + <arguments> + <argument name="storeView" type="string" defaultValue="{{customStore.code}}"/> + </arguments> + + <amOnPage url="{{StorefrontStoreHomePage.url(storeView)}}{{StorefrontCustomerCreatePage.url}}" stepKey="goToCustomerAccountCreatePage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontSignOutActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontSignOutActionGroup.xml new file mode 100644 index 0000000000000..61c5f9ef7c66e --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontSignOutActionGroup.xml @@ -0,0 +1,21 @@ +<?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="StorefrontSignOutActionGroup"> + <annotations> + <description>Clicks on Customer Account. Clicks on 'Sign-Out'. Validates that the success message is present and correct. PLEASE NOTE: The Success Message is hardcoded.</description> + </annotations> + + <click selector="{{StoreFrontSignOutSection.customerAccount}}" stepKey="clickCustomerButton"/> + <click selector="{{StoreFrontSignOutSection.signOut}}" stepKey="clickToSignOut"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <see userInput="You are signed out" stepKey="signOut"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressActionGroup.xml new file mode 100644 index 0000000000000..c439f7529993c --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressActionGroup.xml @@ -0,0 +1,31 @@ +<?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="VerifyCustomerBillingAddressActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address is present and correct on the Storefront Customer Dashboard Address section.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + + <!--Verify customer default billing address--> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressWithStateActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressWithStateActionGroup.xml new file mode 100644 index 0000000000000..7e46fcd7807db --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerBillingAddressWithStateActionGroup.xml @@ -0,0 +1,31 @@ +<?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="VerifyCustomerBillingAddressWithStateActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address, including the State, is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + + <!--Verify customer default billing address--> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerNameOnFrontendActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerNameOnFrontendActionGroup.xml new file mode 100644 index 0000000000000..49ee62e5e86d2 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerNameOnFrontendActionGroup.xml @@ -0,0 +1,27 @@ +<?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="VerifyCustomerNameOnFrontendActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Dashboard page. Validates that the Customer First/Last Name is present and correct.</description> + </annotations> + <arguments> + <argument name="customer"/> + </arguments> + + <!--Verify customer name on frontend--> + <amOnPage url="customer/account/edit/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <click selector="{{StorefrontCustomerSidebarSection.sidebarCurrentTab('Account Information')}}" stepKey="clickAccountInformationFromSidebarCurrentTab"/> + <waitForPageLoad stepKey="waitForAccountInformationTabToOpen"/> + <seeInField selector="{{StorefrontCustomerAccountInformationSection.firstName}}" userInput="{{customer.firstname}}" stepKey="seeAssertCustomerFirstName"/> + <seeInField selector="{{StorefrontCustomerAccountInformationSection.lastName}}" userInput="{{customer.lastname}}" stepKey="seeAssertCustomerLastName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressActionGroup.xml new file mode 100644 index 0000000000000..e6d07ef1afc63 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressActionGroup.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="VerifyCustomerShippingAddressActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <!--Verify customer default shipping address--> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressWithStateActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressWithStateActionGroup.xml new file mode 100644 index 0000000000000..a90a05bead69c --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/VerifyCustomerShippingAddressWithStateActionGroup.xml @@ -0,0 +1,31 @@ +<?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="VerifyCustomerShippingAddressWithStateActionGroup"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address, including the State, is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + + <!--Verify customer default shipping address--> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml new file mode 100644 index 0000000000000..5efcfc0e79b0d --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/_Deprecated_ActionGroup.xml @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- +NOTICE: Action Groups in this file are DEPRECATED and SHOULD NOT BE USED anymore. + Please find the Comment with proper replacement for each of ActionGroups provided. +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateCustomerWithWebSiteAndGroup" deprecated="Use `AdminCreateCustomerWithWebSiteAndGroupActionGroup` instead"> + <annotations> + <description>Goes to the Customer grid page. Click on 'Add New Customer'. Fills provided Customer Data. Fill provided Customer Address data. Assigns Product to Website and Store View. Clicks on Save.</description> + </annotations> + <arguments> + <argument name="customerData" defaultValue="Simple_US_Customer"/> + <argument name="website" type="string" defaultValue="{{_defaultWebsite.name}}"/> + <argument name="storeView" type="string" defaultValue="{{_defaultStore.name}}"/> + </arguments> + + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="goToCustomersPage"/> + <click stepKey="addNewCustomer" selector="{{AdminCustomerGridMainActionsSection.addNewCustomer}}"/> + <selectOption stepKey="selectWebSite" selector="{{AdminCustomerAccountInformationSection.associateToWebsite}}" userInput="{{website}}"/> + <selectOption selector="{{AdminCustomerAccountInformationSection.group}}" userInput="{{customerData.group}}" stepKey="selectCustomerGroup"/> + <fillField stepKey="FillFirstName" selector="{{AdminCustomerAccountInformationSection.firstName}}" userInput="{{customerData.firstname}}"/> + <fillField stepKey="FillLastName" selector="{{AdminCustomerAccountInformationSection.lastName}}" userInput="{{customerData.lastname}}"/> + <fillField stepKey="FillEmail" selector="{{AdminCustomerAccountInformationSection.email}}" userInput="{{customerData.email}}"/> + <selectOption stepKey="selectStoreView" selector="{{AdminCustomerAccountInformationSection.storeView}}" userInput="{{storeView}}"/> + <waitForElement selector="{{AdminCustomerAccountInformationSection.storeView}}" stepKey="waitForCustomerStoreViewExpand"/> + <click stepKey="save" selector="{{AdminCustomerAccountInformationSection.saveCustomer}}"/> + <waitForPageLoad stepKey="waitForCustomersPage"/> + <see stepKey="seeSuccessMessage" userInput="You saved the customer."/> + </actionGroup> + + <actionGroup name="AdminEditCustomerAddressNoZipNoState" extends="AdminEditCustomerAddressesFrom" deprecated="Use `AdminEditCustomerAddressNoZipNoStateActionGroup` instead"> + <annotations> + <description>EXTENDS: AdminEditCustomerAddressesFrom. Removes 'selectState' and 'fillZipCode'. Clicks on 'Set Default' for Billing/Shipping.</description> + </annotations> + + <remove keyForRemoval="selectState"/> + <remove keyForRemoval="fillZipCode"/> + <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> + <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> + </actionGroup> + + <actionGroup name="AdminEditCustomerAddressSetDefaultShippingAndBilling" extends="AdminEditCustomerAddressesFrom" deprecated="Use `AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup` instead"> + <annotations> + <description>EXTENDS: AdminEditCustomerAddressesFrom. Removes 'selectState' and 'fillZipCode'.</description> + </annotations> + + <click selector="{{AdminEditCustomerAddressesSection.defaultBillingAddressButton}}" stepKey="setDefaultBilling" before="setDefaultShipping"/> + <click selector="{{AdminEditCustomerAddressesSection.defaultShippingAddressButton}}" stepKey="setDefaultShipping" before="fillPrefixName"/> + </actionGroup> + + <actionGroup name="EnterCustomerAddressInfo" deprecated="Use `EnterCustomerAddressInfoActionGroup` instead"> + <annotations> + <description>Fills in the provided Customer details (First/Last Name, Company, Phone # and Address) on the Admin Customer creation/edit page. Clicks on the Save button.</description> + </annotations> + <arguments> + <argument name="Address"/> + </arguments> + + <amOnPage url="customer/address/new/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPage"/> + <fillField stepKey="fillFirstName" selector="{{StorefrontCustomerAddressSection.firstName}}" userInput="{{Address.firstname}}"/> + <fillField stepKey="fillLastName" selector="{{StorefrontCustomerAddressSection.lastName}}" userInput="{{Address.lastname}}"/> + <fillField stepKey="fillCompany" selector="{{StorefrontCustomerAddressSection.company}}" userInput="{{Address.company}}"/> + <fillField stepKey="fillPhoneNumber" selector="{{StorefrontCustomerAddressSection.phoneNumber}}" userInput="{{Address.telephone}}"/> + <fillField stepKey="fillStreetAddress1" selector="{{StorefrontCustomerAddressSection.streetAddress1}}" userInput="{{Address.street[0]}}"/> + <fillField stepKey="fillStreetAddress2" selector="{{StorefrontCustomerAddressSection.streetAddress2}}" userInput="{{Address.street[1]}}"/> + <fillField stepKey="fillCityName" selector="{{StorefrontCustomerAddressSection.city}}" userInput="{{Address.city}}"/> + <selectOption stepKey="selectCounty" selector="{{StorefrontCustomerAddressSection.country}}" userInput="{{Address.country_id}}"/> + <selectOption stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvince}}" userInput="{{Address.state}}"/> + <fillField stepKey="fillZip" selector="{{StorefrontCustomerAddressSection.zip}}" userInput="{{Address.postcode}}"/> + <click stepKey="saveAddress" selector="{{StorefrontCustomerAddressSection.saveAddress}}"/> + </actionGroup> + + <!-- Fills State Field instead of selecting it--> + <actionGroup name="EnterCustomerAddressInfoFillState" extends="EnterCustomerAddressInfo" deprecated="Use `CreateSystemBackupActionGroup` instead"> + <annotations> + <description>EXTENDS: EnterCustomerAddressInfo. Fills the State field.</description> + </annotations> + + <fillField stepKey="selectState" selector="{{StorefrontCustomerAddressSection.stateProvinceFill}}" userInput="{{Address.state}}"/> + </actionGroup> + + <actionGroup name="VerifyCustomerBillingAddress" deprecated="Use `VerifyCustomerBillingAddressActionGroup` instead"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address is present and correct on the Storefront Customer Dashboard Address section.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> + </actionGroup> + + <actionGroup name="VerifyCustomerShippingAddress" deprecated="Use `VerifyCustomerShippingAddressActionGroup` instead"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> + </actionGroup> + + <actionGroup name="VerifyCustomerBillingAddressWithState" deprecated="Use `VerifyCustomerBillingAddressWithStateActionGroup` instead"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Billing Address, including the State, is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultBillingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultBillingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultBillingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultBillingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultBillingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultBillingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultBillingAddressTelephone"/> + </actionGroup> + + <actionGroup name="VerifyCustomerShippingAddressWithState" deprecated="Use `VerifyCustomerShippingAddressWithStateActionGroup` instead"> + <annotations> + <description>Goes to the Storefront Customer Dashboard Address area. Validates that the provided Customer Shipping Address, including the State, is present and correct.</description> + </annotations> + <arguments> + <argument name="address"/> + </arguments> + + <amOnPage url="customer/address/index/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.firstname}} {{address.lastname}}" stepKey="seeAssertCustomerDefaultShippingAddressFirstnameAndLastname"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.company}}" stepKey="seeAssertCustomerDefaultShippingAddressCompany"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[0]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.street[1]}}" stepKey="seeAssertCustomerDefaultShippingAddressStreet1"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.city}}, {{address.state}}, {{address.postcode}}" stepKey="seeAssertCustomerDefaultShippingAddressCityAndPostcode"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.country}}" stepKey="seeAssertCustomerDefaultShippingAddressCountry"/> + <see selector="{{StorefrontCustomerAddressesSection.defaultShippingAddress}}" userInput="{{address.telephone}}" stepKey="seeAssertCustomerDefaultShippingAddressTelephone"/> + </actionGroup> + + <actionGroup name="VerifyCustomerNameOnFrontend" deprecated="Use `VerifyCustomerNameOnFrontendActionGroup` instead"> + <annotations> + <description>Goes to the Storefront Customer Dashboard page. Validates that the Customer First/Last Name is present and correct.</description> + </annotations> + <arguments> + <argument name="customer"/> + </arguments> + + <amOnPage url="customer/account/edit/" stepKey="goToAddressPage"/> + <waitForPageLoad stepKey="waitForAddressPageLoad"/> + <click selector="{{StorefrontCustomerSidebarSection.sidebarCurrentTab('Account Information')}}" stepKey="clickAccountInformationFromSidebarCurrentTab"/> + <waitForPageLoad stepKey="waitForAccountInformationTabToOpen"/> + <seeInField selector="{{StorefrontCustomerAccountInformationSection.firstName}}" userInput="{{customer.firstname}}" stepKey="seeAssertCustomerFirstName"/> + <seeInField selector="{{StorefrontCustomerAccountInformationSection.lastName}}" userInput="{{customer.lastname}}" stepKey="seeAssertCustomerLastName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml index 08e13885d10d4..e31be78185aaf 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml @@ -327,6 +327,7 @@ <data key="postcode">10789</data> <data key="telephone">333-33-333-33</data> <data key="country">Germany</data> + <data key="state">Berlin</data> </entity> <entity name="US_Address_California"> <data key="firstname">John</data> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index b9227505871cf..49fa60436ed5a 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -354,4 +354,18 @@ <data key="website_id">0</data> <requiredEntity type="address">US_Address_AE</requiredEntity> </entity> + <entity name="Simple_US_Customer_CA_NY_Addresses" type="customer"> + <data key="group_id">1</data> + <data key="default_billing">true</data> + <data key="default_shipping">true</data> + <data key="email" unique="prefix">John.Doe@example.com</data> + <data key="firstname">John</data> + <data key="lastname">Doe</data> + <data key="fullname">John Doe</data> + <data key="password">pwdTest123!</data> + <data key="store_id">0</data> + <data key="website_id">0</data> + <requiredEntity type="address">US_Address_CA</requiredEntity> + <requiredEntity type="address">US_Address_NY_Not_Default_Address</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminAddNewDefaultBillingShippingCustomerAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminAddNewDefaultBillingShippingCustomerAddressTest.xml index fba7ebd2d4d5e..5600b6088cfe5 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminAddNewDefaultBillingShippingCustomerAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminAddNewDefaultBillingShippingCustomerAddressTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customers. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeCustomerGenderInCustomersGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeCustomerGenderInCustomersGridTest.xml index 7ca9a6993f2fc..30c441796c435 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeCustomerGenderInCustomersGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeCustomerGenderInCustomersGridTest.xml @@ -30,7 +30,7 @@ <waitForPageLoad stepKey="waitForCustomersGrid"/> <actionGroup ref="AdminResetFilterInCustomerGrid" stepKey="resetFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open customers grid page, filter by created customer--> <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterCustomerGridByEmail"> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml index 2478334de3baf..908977da25d36 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminChangeSingleCustomerGroupViaGridTest.xml @@ -31,7 +31,7 @@ <deleteData createDataKey="createCustomerGroup" stepKey="deleteCustomerGroup"/> <actionGroup ref="NavigateToAllCustomerPage" stepKey="navigateToCustomersPage"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCustomersGridFilter"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="NavigateToAllCustomerPage" stepKey="navigateToCustomersPage"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsNoTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsNoTest.xml index be96765920bf5..aa23fc0670a88 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsNoTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsNoTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="AdminNavigateNewCustomerActionGroup" stepKey="navigateToNewCustomer"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsYesTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsYesTest.xml index 87cba0c10dbc1..d7c4fb2d68772 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsYesTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCheckDefaultValueDisableAutoGroupChangeIsYesTest.xml @@ -26,7 +26,7 @@ <after> <magentoCLI command="config:set customer/create_account/viv_disable_auto_group_assign_default 0" stepKey="setConfigDefaultIsNo"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="AdminNavigateNewCustomerActionGroup" stepKey="navigateToNewCustomer"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerGroupAlreadyExistsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerGroupAlreadyExistsTest.xml index 6b1c1f29f97fc..dd065adc7f417 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerGroupAlreadyExistsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerGroupAlreadyExistsTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Steps: 1. Log in to backend as admin user. 2. Navigate to Stores > Other Settings > Customer Groups. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerRetailerWithoutAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerRetailerWithoutAddressTest.xml index 36592ab38e91d..436d7838fc6b7 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerRetailerWithoutAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerRetailerWithoutAddressTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteCustomer"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter the customer From grid--> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml index a11fb9d0eaa8f..2021b589790cf 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerTest.xml @@ -23,7 +23,7 @@ <magentoCLI command="indexer:reindex customer_grid" stepKey="reindexCustomerGrid"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryPolandTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryPolandTest.xml index d2435a093046a..3482f150ebaad 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryPolandTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryPolandTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter the created customer From grid--> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryUSATest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryUSATest.xml index a487571c43534..7d19f2fcf096b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryUSATest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCountryUSATest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter the customer From grid--> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCustomGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCustomGroupTest.xml index 872da149ed0b2..e16a01bc3222b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCustomGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithCustomGroupTest.xml @@ -27,7 +27,7 @@ <argument name="email" value="{{CustomerEntityOne.email}}" /> </actionGroup> <deleteData createDataKey="customerGroup" stepKey="deleteCustomerGroup"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open New Customer Page --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithPrefixTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithPrefixTest.xml index 1b901a7b3e1cd..6b2655b5deaaf 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithPrefixTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithPrefixTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteCustomer"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open New Customer Page and create a customer with Prefix and Suffix--> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithoutAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithoutAddressTest.xml index fe4bb3ee59e6e..7889f2be57a4c 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithoutAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateCustomerWithoutAddressTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteCustomer"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open New Customer Page --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontSignupNewsletterTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontSignupNewsletterTest.xml index 5d09f819bcbc0..3810da9d62427 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontSignupNewsletterTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontSignupNewsletterTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer on storefront and signup news letter--> @@ -51,4 +51,4 @@ <waitForPageLoad stepKey="waitForNewsletterTabToOpen"/> <seeCheckboxIsChecked selector="{{AdminEditCustomerNewsletterSection.subscribedStatus('1')}}" stepKey="seeAssertSubscribedToNewsletterCheckboxIsChecked"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontTest.xml index fc65a271a8196..116ba3773efff 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerOnStorefrontTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer on storefront and perform the asserts--> @@ -37,4 +37,4 @@ <argument name="customer" value="CustomerEntityOne"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerTest.xml index de4ab9ffaa121..49d23c7787554 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateNewCustomerTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteCustomer"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open New Customer Page --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateRetailCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateRetailCustomerGroupTest.xml index 6e08d98a53c56..e0c1c0012f5bc 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateRetailCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateRetailCustomerGroupTest.xml @@ -27,7 +27,7 @@ <argument name="customerGroupName" value="{{CustomCustomerGroup.code}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Steps: 1. Log in to backend as admin user. 2. Navigate to Stores > Other Settings > Customer Groups. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateTaxClassCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateTaxClassCustomerGroupTest.xml index 4b539ec350435..d89b755492cec 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateTaxClassCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCreateTaxClassCustomerGroupTest.xml @@ -33,7 +33,7 @@ </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilters"/> <deleteData createDataKey="createCustomerTaxClass" stepKey="deleteCustomerTaxClass"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Steps: 1. Log in to backend as admin user. 2. Navigate to Stores > Other Settings > Customer Groups. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomerSubscribeNewsletterPerWebsiteTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomerSubscribeNewsletterPerWebsiteTest.xml index 6c1a27c395917..06c0593ad00c4 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomerSubscribeNewsletterPerWebsiteTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomerSubscribeNewsletterPerWebsiteTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{secondCustomWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> </after> @@ -98,4 +98,4 @@ <argument name="storeView" value="SecondStoreUnique"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersAllCustomersNavigateMenuTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersAllCustomersNavigateMenuTest.xml index 76e4407675e4c..d4551c0cd0af9 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersAllCustomersNavigateMenuTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersAllCustomersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToAllCustomerPage"> <argument name="menuUiId" value="{{AdminMenuCustomers.dataUiId}}"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersCustomerGroupsNavigateMenuTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersCustomerGroupsNavigateMenuTest.xml index 13a4b1c714337..7c1a0722ef912 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersCustomerGroupsNavigateMenuTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersCustomerGroupsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToCustomerGroupsPage"> <argument name="menuUiId" value="{{AdminMenuCustomers.dataUiId}}"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersNowOnlineNavigateMenuTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersNowOnlineNavigateMenuTest.xml index e9eb7803e01ea..828fc60f0b77f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersNowOnlineNavigateMenuTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminCustomersNowOnlineNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToNowOnlinePage"> <argument name="menuUiId" value="{{AdminMenuCustomers.dataUiId}}"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridTest.xml index 4f501c27352bf..d4af9ab58a299 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customerts. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridViaMassActionsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridViaMassActionsTest.xml index a703c5a7c5d92..05926e7aefc92 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridViaMassActionsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerAddressesFromTheGridViaMassActionsTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customerts. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerTest.xml index 7fef916fc458a..b5ade97dbb968 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteCustomerTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Delete created customer --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteDefaultBillingCustomerAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteDefaultBillingCustomerAddressTest.xml index bb455677d5e94..54ea673f7249f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteDefaultBillingCustomerAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminDeleteDefaultBillingCustomerAddressTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customers. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminEditDefaultBillingShippingCustomerAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminEditDefaultBillingShippingCustomerAddressTest.xml index df317c8bf7012..4f69a9bbfb695 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminEditDefaultBillingShippingCustomerAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminEditDefaultBillingShippingCustomerAddressTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customers. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml index d278b6c52d330..1822f427ec389 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml @@ -30,7 +30,7 @@ <deleteData createDataKey="createSecondCustomer" stepKey="deleteSecondCustomer"/> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> <actionGroup ref="AdminResetFilterInCustomerAddressGrid" stepKey="clearCustomerGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Step 1: Go to Customers > All Customers--> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminPanelIsFrozenIfStorefrontIsOpenedViaCustomerViewTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminPanelIsFrozenIfStorefrontIsOpenedViaCustomerViewTest.xml index 16125c6ddf250..0eeab8cb36c2e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminPanelIsFrozenIfStorefrontIsOpenedViaCustomerViewTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminPanelIsFrozenIfStorefrontIsOpenedViaCustomerViewTest.xml @@ -28,7 +28,7 @@ <after> <deleteData createDataKey="createSimpleCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPage"> <argument name="customer" value="$simpleCustomer$"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminResetCustomerPasswordTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminResetCustomerPasswordTest.xml index fb67838e941b6..afe8dbef99916 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminResetCustomerPasswordTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminResetCustomerPasswordTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminSearchCustomerAddressByKeywordTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminSearchCustomerAddressByKeywordTest.xml index 9f1c5e8cd923a..6be675140c555 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminSearchCustomerAddressByKeywordTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminSearchCustomerAddressByKeywordTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customerts. @@ -44,4 +44,4 @@ <waitForPageLoad stepKey="waitForCustomerAddressesGridPageLoad"/> <seeNumberOfElements userInput="1" selector="{{AdminCustomerAddressesGridSection.rowsInGrid}}" stepKey="seeOnlyOneCustomerAddressesInGrid"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultBillingAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultBillingAddressTest.xml index db8d4e1ee1eea..b0de96782f0f5 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultBillingAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultBillingAddressTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customers. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultShippingAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultShippingAddressTest.xml index 6e83218176904..dfeb868959d54 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultShippingAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminSetCustomerDefaultShippingAddressTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- - Step1. Login to admin and go to Customers > All Customers. diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminUpdateCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminUpdateCustomerTest.xml index f58f23dee4235..dc357976887d9 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminUpdateCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminUpdateCustomerTest.xml @@ -30,7 +30,7 @@ <amOnPage stepKey="goToCustomersGridPage" url="{{AdminCustomerPage.url}}"/> <waitForPageLoad stepKey="waitForCustomersGrid"/> <actionGroup stepKey="resetFilter" ref="AdminResetFilterInCustomerGrid"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminCustomerPage.url}}edit/id/$$customer.id$$/" stepKey="openCustomerEditPage"/> @@ -42,7 +42,7 @@ <argument name="email" value="updated$$customer.email$$"/> </actionGroup> <!--Update Customer Addresses --> - <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressSetDefaultShippingAndBilling"> + <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressSetDefaultShippingAndBillingActionGroup"> <argument name="customerAddress" value="CustomerAddressSimple"/> </actionGroup> <actionGroup stepKey="saveAndCheckSuccessMessage" ref="AdminSaveCustomerAndAssertSuccessMessage"/> @@ -115,7 +115,7 @@ <remove keyForRemoval="checkCustomerAccountInformation"/> <!--Update Customer Addresses With No Zip and No State --> - <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressNoZipNoState"> + <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressNoZipNoStateActionGroup"> <argument name="customerAddress" value="addressNoZipNoState"/> </actionGroup> @@ -170,7 +170,7 @@ <remove keyForRemoval="checkDefaultShipping"/> <!--Update Customer Addresses With Default Billing and Shipping Unchecked --> - <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressesFrom"> + <actionGroup stepKey="editCustomerAddress" ref="AdminEditCustomerAddressesFromActionGroup"> <argument name="customerAddress" value="CustomerAddressSimple"/> </actionGroup> @@ -221,7 +221,7 @@ </before> <after> <deleteData stepKey="deleteCustomer" createDataKey="customer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminCustomerPage.url}}edit/id/$$customer.id$$/" stepKey="openCustomerEditPage"/> @@ -305,4 +305,4 @@ <argument name="text" value="{{UK_Not_Default_Address.street[0]}}"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCreateCustomerRequiredFieldsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCreateCustomerRequiredFieldsTest.xml index 7dab6eefde8ec..72661e4505322 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCreateCustomerRequiredFieldsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCreateCustomerRequiredFieldsTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open New Customer Page --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressRequiredFieldsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressRequiredFieldsTest.xml index bfb47dc9e1911..41efec9d87b18 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressRequiredFieldsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressRequiredFieldsTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Created Customer --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressStateContainValuesOnceTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressStateContainValuesOnceTest.xml index daab5fd2061fb..e9b0e1723c6ba 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressStateContainValuesOnceTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminVerifyCustomerAddressStateContainValuesOnceTest.xml @@ -29,7 +29,7 @@ <argument name="customerEmail" value="Simple_US_Customer.email"/> </actionGroup> <actionGroup ref="AdminClearCustomersFiltersActionGroup" stepKey="clearFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Customers > All Customers.--> @@ -52,7 +52,7 @@ <seeNumberOfElements userInput="1" selector="{{AdminCustomerAddressesSection.regionId(US_Address_NY.state)}}" stepKey="seeOnlyOneRegionInSelectStateForFirstCustomer"/> <!--Go to Customers > All customers, Click Add new Customers, fill all necessary fields, Save--> - <actionGroup ref="AdminCreateCustomerWithWebSiteAndGroup" stepKey="createSimpleUSCustomerWithoutAddress"/> + <actionGroup ref="AdminCreateCustomerWithWebSiteAndGroupActionGroup" stepKey="createSimpleUSCustomerWithoutAddress"/> <!--Select new created customer, Click Edit mode--> <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="openEditCustomerPageWithoutAddresses"> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml index 194c6e6164f8c..7cd69b4e17472 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AllowedCountriesRestrictionApplyOnBackendTest.xml @@ -23,7 +23,7 @@ <createData entity="SimpleProduct" stepKey="createSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <!--Create new website,store and store view--> <comment userInput="Create new website,store and store view" stepKey="createWebsite"/> <amOnPage url="{{AdminSystemStorePage.url}}" stepKey="goToAdminSystemStorePage"/> @@ -59,7 +59,7 @@ </actionGroup> <actionGroup ref="SetWebsiteCountryOptionsToDefaultActionGroup" stepKey="setCountryOptionsToDefault"/> <createData entity="CustomerAccountSharingSystemValue" stepKey="setAccountSharingToSystemValue"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </after> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml index 7de52875d4341..eb46a9d2b1ace 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/ChangeCustomerGroupTest.xml @@ -35,7 +35,7 @@ <argument name="customerGroupName" value="{{CustomerGroupChange.code}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminCreateCustomerGroupActionGroup" stepKey="createCustomerGroup"> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml index b19966e0102b6..b03478c5be684 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/DeleteCustomerGroupTest.xml @@ -29,7 +29,7 @@ </before> <after> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Customer Group success delete message--> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml index bf8844b2cc7ab..501baca64318f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml @@ -11,20 +11,22 @@ <test name="EndToEndB2CLoggedInUserTest"> <annotations> <features value="End to End scenarios"/> - <stories value="B2C logged in user - MAGETWO-72524"/> + <stories value="B2C logged in user - MC-25681"/> <group value="e2e"/> <title value="You should be able to pass End to End B2C Logged In User scenario"/> <description value="New user signup and browses catalog, searches for product, adds product to cart, adds product to wishlist, compares products, uses coupon code and checks out."/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-87653"/> - <skip> - <issueId value="MC-17140"/> - </skip> + <testCaseId value="MC-25681"/> + <group value="SearchEngineMysql"/> </annotations> <before> <resetCookie userInput="PHPSESSID" stepKey="resetCookieForCart"/> </before> <after> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="DeleteCustomerFromAdminActionGroup" stepKey="deleteCustomerFromAdmin"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> <actionGroup ref="logout" stepKey="adminLogout"/> </after> <!-- Step 0: User signs up an account --> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml index 5cce64495bbd2..0d9f17096b26e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/SearchByEmailInCustomerGridTest.xml @@ -28,7 +28,7 @@ <deleteData createDataKey="createSecondCustomer" stepKey="deleteSecondCustomer"/> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> <actionGroup ref="AdminResetFilterInCustomerAddressGrid" stepKey="clearCustomerGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Step 1: Go to Customers > All Customers--> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontAddCustomerAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontAddCustomerAddressTest.xml index e2c55eb3962f2..ac6612184e32c 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontAddCustomerAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontAddCustomerAddressTest.xml @@ -24,7 +24,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="DeleteCustomer"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Log in to Storefront as Customer 1 --> @@ -101,7 +101,7 @@ </before> <after> <deleteData createDataKey="createCustomer" stepKey="DeleteCustomer"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Log in to Storefront as Customer 1 --> @@ -118,4 +118,4 @@ <see userInput="{{US_Address_TX.postcode}}" selector="{{StorefrontCustomerAddressesSection.addressesList}}" stepKey="checkNewAddressesPostcodeOnDefaultShipping"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml index 4c35cdbdb7cbb..d154893f70588 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml @@ -72,7 +72,7 @@ </actionGroup> <!--Go to My account > Address book--> - <actionGroup ref="EnterCustomerAddressInfoFillState" stepKey="enterAddressInfo"> + <actionGroup ref="EnterCustomerAddressInfoFillStateActionGroup" stepKey="enterAddressInfo"> <argument name="Address" value="UK_Simple_Address"/> </actionGroup> @@ -143,7 +143,7 @@ </actionGroup> <!--Log Out--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml index 40b05153f1a74..8e4f9edc085a4 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml @@ -18,7 +18,7 @@ <group value="catalog"/> <group value="mtf_migrated"/> </annotations> - + <before> <magentoCLI stepKey="addDownloadableDomain" command="downloadable:domains:add static.magento.com"/> <!-- Create Simple Customer --> @@ -111,7 +111,7 @@ <after> <magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove static.magento.com"/> <!-- Logout --> - <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin1"/> <!-- Delete Created Entities --> <deleteData createDataKey="createSimpleCustomer1" stepKey="deleteSimpleCustomer1"/> @@ -124,6 +124,10 @@ <deleteData createDataKey="createBundleProduct1" stepKey="deleteBundleProduct1"/> <deleteData createDataKey="createGroupedProduct1" stepKey="deleteGroupedProduct1"/> <deleteData createDataKey="createDownloadableProduct1" stepKey="deleteDownloadableProduct1"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer1"> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateCustomerTest.xml index 7d51f97f2463a..7899f4ac53132 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateCustomerTest.xml @@ -20,11 +20,11 @@ <group value="create"/> </annotations> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> <argument name="Customer" value="CustomerEntityOne"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontDeleteCustomerAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontDeleteCustomerAddressTest.xml index 7a96616885468..fb08a07a7c319 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontDeleteCustomerAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontDeleteCustomerAddressTest.xml @@ -27,7 +27,7 @@ <fillField stepKey="fillEmail" userInput="$$createCustomer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> <fillField stepKey="fillPassword" userInput="$$createCustomer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddressInfo"> <argument name="Address" value="US_Address_NY"/> </actionGroup> <see userInput="You saved the address." stepKey="verifyAddressCreated"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressBelgiumTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressBelgiumTest.xml index d36d640c5ad17..f45935b698fb5 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressBelgiumTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressBelgiumTest.xml @@ -28,23 +28,23 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update customer address Belgium in storefront--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddress"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddress"> <argument name="Address" value="updateCustomerBelgiumAddress"/> </actionGroup> <!--Verify customer address save success message--> <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the address." stepKey="seeAssertCustomerAddressSuccessSaveMessage"/> <!--Verify customer default billing address--> - <actionGroup ref="VerifyCustomerBillingAddressWithState" stepKey="verifyBillingAddress"> + <actionGroup ref="VerifyCustomerBillingAddressWithStateActionGroup" stepKey="verifyBillingAddress"> <argument name="address" value="updateCustomerBelgiumAddress"/> </actionGroup> <!--Verify customer default shipping address--> - <actionGroup ref="VerifyCustomerShippingAddressWithState" stepKey="verifyShippingAddress"> + <actionGroup ref="VerifyCustomerShippingAddressWithStateActionGroup" stepKey="verifyShippingAddress"> <argument name="address" value="updateCustomerBelgiumAddress"/> </actionGroup> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressChinaTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressChinaTest.xml index 285de8d777b48..87390beaa50f9 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressChinaTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressChinaTest.xml @@ -28,23 +28,23 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update customer address in storefront--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddress"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddress"> <argument name="Address" value="updateCustomerChinaAddress"/> </actionGroup> <!--Verify customer address save success message--> <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the address." stepKey="seeAssertCustomerAddressSuccessSaveMessage"/> <!--Verify customer default billing address--> - <actionGroup ref="VerifyCustomerBillingAddressWithState" stepKey="verifyBillingAddress"> + <actionGroup ref="VerifyCustomerBillingAddressWithStateActionGroup" stepKey="verifyBillingAddress"> <argument name="address" value="updateCustomerChinaAddress"/> </actionGroup> <!--Verify customer default shipping address--> - <actionGroup ref="VerifyCustomerShippingAddressWithState" stepKey="verifyShippingAddress"> + <actionGroup ref="VerifyCustomerShippingAddressWithStateActionGroup" stepKey="verifyShippingAddress"> <argument name="address" value="updateCustomerChinaAddress"/> </actionGroup> </test> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressFranceTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressFranceTest.xml index dae456c96a679..2f6f4fb5e2dca 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressFranceTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressFranceTest.xml @@ -29,24 +29,24 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update customer address France in storefront--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddress"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddress"> <argument name="Address" value="updateCustomerFranceAddress"/> </actionGroup> <!--Verify customer address save success message--> <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the address." stepKey="seeAssertCustomerAddressSuccessSaveMessage"/> <!--Verify customer default billing address--> - <actionGroup ref="VerifyCustomerBillingAddressWithState" stepKey="verifyBillingAddress"> + <actionGroup ref="VerifyCustomerBillingAddressWithStateActionGroup" stepKey="verifyBillingAddress"> <argument name="address" value="updateCustomerFranceAddress"/> </actionGroup> <!--Verify customer default shipping address--> - <actionGroup ref="VerifyCustomerShippingAddressWithState" stepKey="verifyShippingAddress"> + <actionGroup ref="VerifyCustomerShippingAddressWithStateActionGroup" stepKey="verifyShippingAddress"> <argument name="address" value="updateCustomerFranceAddress"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressUKTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressUKTest.xml index 7b6e695aa8dc4..d51bc1dcc9b18 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressUKTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontUpdateCustomerAddressUKTest.xml @@ -29,29 +29,29 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{CustomerEntityOne.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update customer address UK in storefront--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddress"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddress"> <argument name="Address" value="updateCustomerUKAddress"/> </actionGroup> <!--Verify customer address save success message--> <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the address." stepKey="seeAssertCustomerAddressSuccessSaveMessage"/> <!--Verify customer default billing address--> - <actionGroup ref="VerifyCustomerBillingAddress" stepKey="verifyBillingAddress"> + <actionGroup ref="VerifyCustomerBillingAddressActionGroup" stepKey="verifyBillingAddress"> <argument name="address" value="updateCustomerUKAddress"/> </actionGroup> <!--Verify customer default shipping address--> - <actionGroup ref="VerifyCustomerShippingAddress" stepKey="verifyShippingAddress"> + <actionGroup ref="VerifyCustomerShippingAddressActionGroup" stepKey="verifyShippingAddress"> <argument name="address" value="updateCustomerUKAddress"/> </actionGroup> <!--Verify customer name on frontend--> - <actionGroup ref="VerifyCustomerNameOnFrontend" stepKey="verifyVerifyCustomerName"> + <actionGroup ref="VerifyCustomerNameOnFrontendActionGroup" stepKey="verifyVerifyCustomerName"> <argument name="customer" value="CustomerEntityOne"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml index e11404db9a9a9..67aa050907f30 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml @@ -29,29 +29,29 @@ <actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteNewUser"> <argument name="email" value="{{Colorado_US_Customer.email}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Update customer address in storefront--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddress"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddress"> <argument name="Address" value="updateCustomerNoXSSInjection"/> </actionGroup> <!--Verify customer address save success message--> <see selector="{{AdminCustomerMessagesSection.successMessage}}" userInput="You saved the address." stepKey="seeAssertCustomerAddressSuccessSaveMessage"/> <!--Verify customer default billing address--> - <actionGroup ref="VerifyCustomerBillingAddressWithState" stepKey="verifyBillingAddress"> + <actionGroup ref="VerifyCustomerBillingAddressWithStateActionGroup" stepKey="verifyBillingAddress"> <argument name="address" value="updateCustomerNoXSSInjection"/> </actionGroup> <!--Verify customer default shipping address--> - <actionGroup ref="VerifyCustomerShippingAddressWithState" stepKey="verifyShippingAddress"> + <actionGroup ref="VerifyCustomerShippingAddressWithStateActionGroup" stepKey="verifyShippingAddress"> <argument name="address" value="updateCustomerNoXSSInjection"/> </actionGroup> <!--Verify customer name on frontend--> - <actionGroup ref="VerifyCustomerNameOnFrontend" stepKey="verifyVerifyCustomerName"> + <actionGroup ref="VerifyCustomerNameOnFrontendActionGroup" stepKey="verifyVerifyCustomerName"> <argument name="customer" value="Colorado_US_Customer"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php index 2e729873961c0..51663861fc8d1 100644 --- a/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/SaveTest.php @@ -269,7 +269,7 @@ protected function setUp() ->getMock(); $this->managementMock = $this->getMockBuilder(AccountManagement::class) ->disableOriginalConstructor() - ->setMethods(['createAccount']) + ->setMethods(['createAccount', 'validateCustomerStoreIdByWebsiteId']) ->getMock(); $this->addressDataFactoryMock = $this->getMockBuilder(AddressInterfaceFactory::class) ->disableOriginalConstructor() @@ -522,6 +522,9 @@ public function testExecuteWithExistentCustomer() ->with('customer/*/edit', ['id' => $customerId, '_current' => true]) ->willReturn(true); + $this->managementMock->method('validateCustomerStoreIdByWebsiteId') + ->willReturn(true); + $this->assertEquals($redirectMock, $this->model->execute()); } diff --git a/app/code/Magento/Customer/Test/Unit/CustomerData/SectionConfigConverterTest.php b/app/code/Magento/Customer/Test/Unit/CustomerData/SectionConfigConverterTest.php index bc1085e295995..b78aa8609607e 100644 --- a/app/code/Magento/Customer/Test/Unit/CustomerData/SectionConfigConverterTest.php +++ b/app/code/Magento/Customer/Test/Unit/CustomerData/SectionConfigConverterTest.php @@ -6,6 +6,7 @@ namespace Magento\Customer\Test\Unit\CustomerData; +use Magento\Framework\App\Arguments\ValidationState; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; class SectionConfigConverterTest extends \PHPUnit\Framework\TestCase @@ -19,6 +20,12 @@ class SectionConfigConverterTest extends \PHPUnit\Framework\TestCase /** @var \DOMDocument */ protected $source; + /** @var \Magento\Framework\Config\Dom config merger */ + private $configMergerClass; + + /** @var ValidationState */ + private $validationStateMock; + protected function setUp() { $this->source = new \DOMDocument(); @@ -26,20 +33,61 @@ protected function setUp() $this->converter = $this->objectManagerHelper->getObject( \Magento\Customer\CustomerData\SectionConfigConverter::class ); + $this->validationStateMock = $this->createMock(ValidationState::class); + } + + /** + * Return newly created instance of a config merger + * + * @param string $mergerClass + * @param string $initialContents + * @return \Magento\Framework\Config\Dom + * @throws \UnexpectedValueException + */ + private function createConfig($mergerClass, $initialContents) + { + $this->validationStateMock->method('isValidationRequired')->willReturn(\false); + return new $mergerClass( + $initialContents, + $this->validationStateMock, + [ + '/config/action' => 'name', + '/config/action/section' => 'name', + ], + null, + null + ); } public function testConvert() { $this->source->loadXML(file_get_contents(__DIR__ . '/_files/sections.xml')); + $this->configMergerClass = $this->createConfig( + 'Magento\Framework\Config\Dom', + file_get_contents(__DIR__ . '/_files/sections.xml') + ); + + $this->configMergerClass->merge(file_get_contents(__DIR__ . '/_files/sections2.xml')); + $this->assertEquals( [ 'sections' => [ - 'customer/account/logout' => '*', - 'customer/account/editpost' => ['account'], + 'sales/guest/reorder' => ['account'], + 'sales/order/reorder' => ['account', 'cart'], + 'stores/store/switch' => ['*'], + 'directory/currency/switch' => ['*'], + 'customer/account/logout' => ['account', 'cart'], + 'customer/account/editpost' => ['account', 'acc', 'cart'], + 'checkout/cart/delete' => ['*'], + 'customer/account/createpost' => ['*'], + 'catalog/product_compare/add' => ['*'], + 'catalog/product_compare/remove' => ['account', 'acc'], + 'catalog/product_compare/clear' => ['*'], + 'checkout/cart/add' => ['*'], ], ], - $this->converter->convert($this->source) + $this->converter->convert($this->configMergerClass->getDom()) ); } } diff --git a/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections.xml b/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections.xml index 0b4250f678a68..fac1ef42c8a67 100644 --- a/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections.xml +++ b/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections.xml @@ -7,8 +7,56 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"> - <action name="customer/account/logout"/> + <!-- Actions 1-4 are specified in sections.xml file only --> + <!-- 1 - Action has one Section --> + <action name="sales/guest/reorder"> + <section name="account"/> + </action> + <!-- 2 - Action has two Sections --> + <action name="sales/order/reorder"> + <section name="account"/> + <section name="cart"/> + </action> + <!-- 3 - Action has two Sections and "*" --> + <action name="stores/store/switch"> + <section name="account"/> + <section name="*"/> + <section name="cart"/> + </action> + <!-- 4 - Action has "empty_section" --> + <action name="directory/currency/switch"/> + <!-- Actions 5-12 are specified in files sections.xml and sections2.xml for merging --> + <!-- 5 - Action in both files has unique Section --> + <action name="customer/account/logout"> + <section name="account"/> + </action> + <!-- 6 - Action in both files has at least one identical Section --> <action name="customer/account/editPost"> <section name="account"/> + <section name="acc"/> + </action> + <!-- 7 - Action in both files has at least one identical Section and "*" --> + <action name="checkout/cart/delete"> + <section name="account"/> + <section name="acc"/> + </action> + <!-- 8 - Action in both files has Section and "*" --> + <action name="customer/account/createPost"> + <section name="account"/> + </action> + <!-- 9 - Action in both files has "*" and "*" --> + <action name="catalog/product_compare/add"> + <section name="*"/> + </action> + <!-- 10 - Action in both files has Section and "empty_section" --> + <action name="catalog/product_compare/remove"> + <section name="account"/> + <section name="acc"/> + </action> + <!-- 11 - Action in both files has "empty_section" and "empty_section" --> + <action name="catalog/product_compare/clear"/> + <!-- 12 - Action in both files has "*" and "empty_section" --> + <action name="checkout/cart/add"> + <section name="*"/> </action> </config> diff --git a/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections2.xml b/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections2.xml new file mode 100644 index 0000000000000..c3c2b29b358bd --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections2.xml @@ -0,0 +1,40 @@ +<?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:module:Magento_Customer:etc/sections.xsd"> + <!-- Actions 5-12 are specified in files sections.xml and sections2.xml for merging --> + <!-- 5 - Action in both files has unique Section --> + <action name="customer/account/logout"> + <section name="cart"/> + </action> + <!-- 6 - Action in both files has at least one identical Section --> + <action name="customer/account/editPost"> + <section name="cart"/> + <section name="account"/> + </action> + <!-- 7 - Action in both files has at least one identical Section and "*" --> + <action name="checkout/cart/delete"> + <section name="cart"/> + <section name="*"/> + <section name="account"/> + </action> + <!-- 8 - Action in both files has Section and "*" --> + <action name="customer/account/createPost"> + <section name="*"/> + </action> + <!-- 9 - Action in both files has "*" and "*" --> + <action name="catalog/product_compare/add"> + <section name="*"/> + </action> + <!-- 10 - Action in both files has Section and "empty_section" --> + <action name="catalog/product_compare/remove"/> + <!-- 11 - Action in both files has "empty_section" and "empty_section" --> + <action name="catalog/product_compare/clear"/> + <!-- 12 - Action in both files has "*" and "empty_section" --> + <action name="checkout/cart/add"/> +</config> diff --git a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php index 0138c6c709b7c..5c57012e0505c 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -11,14 +11,19 @@ use Magento\Customer\Model\Account\Redirect; use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; +use Magento\Framework\Stdlib\Cookie\PublicCookieMetadata; +use Magento\Framework\Stdlib\CookieManagerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\Url\HostChecker; use Magento\Store\Model\ScopeInterface; +use PHPUnit\Framework\TestCase; +use PHPUnit\FrameworkMockObject\MockObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class RedirectTest extends \PHPUnit\Framework\TestCase +class RedirectTest extends TestCase { /** * @var Redirect @@ -26,123 +31,119 @@ class RedirectTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\RequestInterface + * @var MockObject|\Magento\Framework\App\RequestInterface */ protected $request; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Session + * @var MockObject|\Magento\Customer\Model\Session */ protected $customerSession; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\App\Config\ScopeConfigInterface + * @var MockObject|\Magento\Framework\App\Config\ScopeConfigInterface */ protected $scopeConfig; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\StoreManagerInterface + * @var MockObject|\Magento\Store\Model\StoreManagerInterface */ protected $storeManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Store\Model\Store + * @var MockObject|\Magento\Store\Model\Store */ protected $store; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\UrlInterface + * @var MockObject|\Magento\Framework\UrlInterface */ protected $url; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Url\DecoderInterface + * @var MockObject|\Magento\Framework\Url\DecoderInterface */ protected $urlDecoder; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Url + * @var MockObject|\Magento\Customer\Model\Url */ protected $customerUrl; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\Redirect + * @var MockObject|\Magento\Framework\Controller\Result\Redirect */ protected $resultRedirect; /** - * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Controller\Result\Forward + * @var MockObject|\Magento\Framework\Controller\Result\Forward */ protected $resultForward; /** - * @var ResultFactory | \PHPUnit_Framework_MockObject_MockObject + * @var ResultFactory|MockObject */ protected $resultFactory; /** - * @var HostChecker | \PHPUnit_Framework_MockObject_MockObject + * @var CookieMetadataFactory|MockObject + */ + protected $cookieMetadataFactory; + + /** + * @var HostChecker|MockObject */ private $hostChecker; + /** + * @inheritdoc + */ protected function setUp() { $this->request = $this->getMockForAbstractClass(\Magento\Framework\App\RequestInterface::class); - $this->customerSession = $this->getMockBuilder(\Magento\Customer\Model\Session::class) ->disableOriginalConstructor() - ->setMethods([ - 'getLastCustomerId', - 'isLoggedIn', - 'getId', - 'setLastCustomerId', - 'unsBeforeAuthUrl', - 'getBeforeAuthUrl', - 'setBeforeAuthUrl', - 'getAfterAuthUrl', - 'setAfterAuthUrl', - 'getBeforeRequestParams', - 'getBeforeModuleName', - 'getBeforeControllerName', - 'getBeforeAction', - ]) + ->setMethods( + [ + 'getLastCustomerId', + 'isLoggedIn', + 'getId', + 'setLastCustomerId', + 'unsBeforeAuthUrl', + 'getBeforeAuthUrl', + 'setBeforeAuthUrl', + 'getAfterAuthUrl', + 'setAfterAuthUrl', + 'getBeforeRequestParams', + 'getBeforeModuleName', + 'getBeforeControllerName', + 'getBeforeAction', + ] + ) ->getMock(); $this->scopeConfig = $this->getMockForAbstractClass(\Magento\Framework\App\Config\ScopeConfigInterface::class); - - $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class) - ->disableOriginalConstructor() - ->getMock(); - + $this->store = $this->createMock(\Magento\Store\Model\Store::class); $this->storeManager = $this->getMockForAbstractClass(\Magento\Store\Model\StoreManagerInterface::class); - $this->storeManager->expects($this->once()) - ->method('getStore') - ->willReturn($this->store); - $this->url = $this->getMockForAbstractClass(\Magento\Framework\UrlInterface::class); $this->urlDecoder = $this->getMockForAbstractClass(\Magento\Framework\Url\DecoderInterface::class); - $this->customerUrl = $this->getMockBuilder(\Magento\Customer\Model\Url::class) - ->setMethods(['DashboardUrl', 'getAccountUrl', 'getLoginUrl', 'getLogoutUrl', 'getDashboardUrl']) - ->disableOriginalConstructor() - ->getMock(); - - $this->resultRedirect = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->resultForward = $this->getMockBuilder(\Magento\Framework\Controller\Result\Forward::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->resultFactory = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->hostChecker = $this->getMockBuilder(HostChecker::class) - ->disableOriginalConstructor() + ->setMethods( + [ + 'DashboardUrl', + 'getAccountUrl', + 'getLoginUrl', + 'getLogoutUrl', + 'getDashboardUrl' + ] + )->disableOriginalConstructor() ->getMock(); + $this->resultRedirect = $this->createMock(\Magento\Framework\Controller\Result\Redirect::class); + $this->resultForward = $this->createMock(\Magento\Framework\Controller\Result\Forward::class); + $this->resultFactory = $this->createMock(\Magento\Framework\Controller\ResultFactory::class); + $this->cookieMetadataFactory = $this->createMock(CookieMetadataFactory::class); + $this->hostChecker = $this->createMock(HostChecker::class); $objectManager = new ObjectManager($this); $this->model = $objectManager->getObject( \Magento\Customer\Model\Account\Redirect::class, @@ -155,12 +156,15 @@ protected function setUp() 'urlDecoder' => $this->urlDecoder, 'customerUrl' => $this->customerUrl, 'resultFactory' => $this->resultFactory, + 'cookieMetadataFactory' => $this->cookieMetadataFactory, 'hostChecker' => $this->hostChecker, ] ); } /** + * Verify get redirect method + * * @param int $customerId * @param int $lastCustomerId * @param string $referer @@ -201,6 +205,9 @@ public function testGetRedirect( ->willReturnSelf(); // Preparations for method prepareRedirectUrl() + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); $this->store->expects($this->once())->method('getBaseUrl')->willReturn($baseUrl); $this->customerSession->expects($this->any())->method('getBeforeAuthUrl')->willReturn($beforeAuthUrl); @@ -244,6 +251,8 @@ public function testGetRedirect( } /** + * Redirect data provider + * * @return array */ public function getRedirectDataProvider() @@ -292,7 +301,12 @@ public function getRedirectDataProvider() ]; } - public function testBeforeRequestParams() + /** + * Verify before request params + * + * @return void + */ + public function testBeforeRequestParams(): void { $requestParams = [ 'param1' => 'value1', @@ -302,6 +316,9 @@ public function testBeforeRequestParams() $controller = 'controller'; $action = 'action'; + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); $this->customerSession->expects($this->exactly(2)) ->method('getBeforeRequestParams') ->willReturn($requestParams); @@ -314,7 +331,6 @@ public function testBeforeRequestParams() $this->customerSession->expects($this->once()) ->method('getBeforeAction') ->willReturn($action); - $this->resultForward->expects($this->once()) ->method('setParams') ->with($requestParams) @@ -331,7 +347,6 @@ public function testBeforeRequestParams() ->method('forward') ->with($action) ->willReturnSelf(); - $this->resultFactory->expects($this->once()) ->method('create') ->with(ResultFactory::TYPE_FORWARD) @@ -340,4 +355,82 @@ public function testBeforeRequestParams() $result = $this->model->getRedirect(); $this->assertSame($this->resultForward, $result); } + + /** + * Verify set redirect cokkie method + * + * @return void + */ + public function testSetRedirectCookie(): void + { + $coockieManagerMock = $this->createMock(CookieManagerInterface::class); + $publicMetadataMock = $this->createMock(PublicCookieMetadata::class); + $routeMock = 'route'; + + $this->model->setCookieManager($coockieManagerMock); + + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getStorePath') + ->willReturn('storePath'); + $this->cookieMetadataFactory->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($publicMetadataMock); + $publicMetadataMock->expects($this->once()) + ->method('setHttpOnly') + ->with(true) + ->willReturnSelf(); + $publicMetadataMock->expects($this->once()) + ->method('setDuration') + ->with(3600) + ->willReturnSelf(); + $publicMetadataMock->expects($this->once()) + ->method('setPath') + ->with('storePath') + ->willReturnSelf(); + $coockieManagerMock->expects($this->once()) + ->method('setPublicCookie') + ->with( + Redirect::LOGIN_REDIRECT_URL, + $routeMock, + $publicMetadataMock + ); + $this->model->setRedirectCookie($routeMock); + } + + /** + * Verify clear redirect cookie + * + * @return void + */ + public function testClearRedirectCookie(): void + { + $coockieManagerMock = $this->createMock(CookieManagerInterface::class); + $publicMetadataMock = $this->createMock(PublicCookieMetadata::class); + + $this->model->setCookieManager($coockieManagerMock); + + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getStorePath') + ->willReturn('storePath'); + $this->cookieMetadataFactory->expects($this->once()) + ->method('createPublicCookieMetadata') + ->willReturn($publicMetadataMock); + $publicMetadataMock->expects($this->once()) + ->method('setPath') + ->with('storePath') + ->willReturnSelf(); + $coockieManagerMock->expects($this->once()) + ->method('deleteCookie') + ->with( + Redirect::LOGIN_REDIRECT_URL, + $publicMetadataMock + ); + $this->model->clearRedirectCookie(); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 3c38cd0f7b4e2..394c3ba43ebd4 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -329,7 +329,6 @@ public function testCreateAccountWithPasswordHashWithExistingCustomer() public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -359,9 +358,9 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -378,9 +377,7 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->atLeastOnce()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -405,7 +402,6 @@ public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() public function testCreateAccountWithPasswordHashWithLocalizedException() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -419,8 +415,7 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() ->method('getId') ->willReturn($defaultStoreId); $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -435,9 +430,9 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -454,9 +449,7 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -481,7 +474,6 @@ public function testCreateAccountWithPasswordHashWithLocalizedException() public function testCreateAccountWithPasswordHashWithAddressException() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -498,8 +490,7 @@ public function testCreateAccountWithPasswordHashWithAddressException() ->method('getId') ->willReturn($defaultStoreId); $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -514,9 +505,9 @@ public function testCreateAccountWithPasswordHashWithAddressException() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -533,9 +524,7 @@ public function testCreateAccountWithPasswordHashWithAddressException() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager ->expects($this->atLeastOnce()) @@ -648,7 +637,6 @@ public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedExce public function testCreateAccountWithoutPassword() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -683,9 +671,8 @@ public function testCreateAccountWithoutPassword() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); + $customer->expects($this->at(10))->method('getStoreId') + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -700,8 +687,7 @@ public function testCreateAccountWithoutPassword() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -861,7 +847,6 @@ public function testCreateAccountInputExceptionExtraLongPassword() public function testCreateAccountWithPassword() { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -940,9 +925,9 @@ public function testCreateAccountWithPassword() $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(11)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -957,8 +942,7 @@ public function testCreateAccountWithPassword() ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -1567,6 +1551,7 @@ public function testChangePassword() ->with($customer); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); + $this->sessionManager->expects($this->atLeastOnce())->method('regenerateId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() @@ -1644,6 +1629,7 @@ function ($string) { $this->sessionManager->method('isSessionExists')->willReturn(false); $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); + $this->sessionManager->expects($this->atLeastOnce())->method('regenerateId'); $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) ->disableOriginalConstructor() ->setMethods(['getSessionId']) @@ -1810,62 +1796,37 @@ public function dataProviderGetConfirmationStatus() /** * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Exception message */ - public function testCreateAccountWithPasswordHashForGuest() + public function testCreateAccountWithPasswordHashForGuestException() { $storeId = 1; - $storeName = 'store_name'; $websiteId = 1; $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) ->disableOriginalConstructor() ->getMock(); - $storeMock->expects($this->once()) - ->method('getId') + $storeMock->method('getId') ->willReturn($storeId); - $storeMock->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $storeMock->expects($this->once()) - ->method('getName') - ->willReturn($storeName); - - $this->storeManager->expects($this->exactly(3)) - ->method('getStore') - ->willReturn($storeMock); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); $customerMock = $this->getMockBuilder(Customer::class) ->disableOriginalConstructor() ->getMock(); - $customerMock->expects($this->exactly(2)) - ->method('getId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) + $customerMock->expects($this->at(1)) ->method('getStoreId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) + ->willReturn($storeId); + $customerMock->expects($this->at(4)) + ->method('getStoreId') + ->willReturn($storeId); + $customerMock->expects($this->at(2)) ->method('getWebsiteId') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setStoreId') - ->with($storeId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setWebsiteId') - ->with($websiteId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setCreatedIn') - ->with($storeName) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setAddresses') - ->with(null) - ->willReturnSelf(); + ->willReturn($websiteId); + $customerMock->expects($this->at(5)) + ->method('getId') + ->willReturn(1); $this->customerRepository ->expects($this->once()) @@ -2030,7 +1991,6 @@ private function prepareDateTimeFactory() public function testCreateAccountUnexpectedValueException(): void { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -2048,8 +2008,7 @@ public function testCreateAccountUnexpectedValueException(): void ->method('getId') ->willReturn($defaultStoreId); $website = $this->createMock(\Magento\Store\Model\Website::class); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') + $website->method('getStoreIds') ->willReturn([1, 2, 3]); $website->expects($this->once()) ->method('getDefaultStore') @@ -2064,9 +2023,9 @@ public function testCreateAccountUnexpectedValueException(): void $customer->expects($this->atLeastOnce()) ->method('getWebsiteId') ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) + $customer->expects($this->at(10)) ->method('getStoreId') - ->willReturn($storeId); + ->willReturn(1); $customer->expects($this->once()) ->method('setStoreId') ->with($defaultStoreId); @@ -2080,8 +2039,7 @@ public function testCreateAccountUnexpectedValueException(): void ->method('get') ->with($customerEmail) ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') + $this->share->method('isWebsiteScope') ->willReturn(true); $this->storeManager->expects($this->atLeastOnce()) ->method('getWebsite') @@ -2162,4 +2120,49 @@ public function testCreateAccountWithStoreNotInWebsite() ->willReturn($website); $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); } + + /** + * Test for validating customer store id by customer website id. + * + * @return void + */ + public function testValidateCustomerStoreIdByWebsiteId(): void + { + $customerMock = $this->getMockBuilder(CustomerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $customerMock->method('getWebsiteId')->willReturn(1); + $customerMock->method('getStoreId')->willReturn(1); + $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->method('getId') + ->willReturn(1); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); + + $this->assertTrue($this->accountManagement->validateCustomerStoreIdByWebsiteId($customerMock)); + } + + /** + * Test for validating customer store id by customer website id with Exception + * + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage The store view is not in the associated website. + */ + public function testValidateCustomerStoreIdByWebsiteIdException(): void + { + $customerMock = $this->getMockBuilder(CustomerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->method('getId') + ->willReturn(1); + $this->storeManager->method('getStores') + ->willReturn([$storeMock]); + + $this->assertTrue($this->accountManagement->validateCustomerStoreIdByWebsiteId($customerMock)); + } } diff --git a/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php b/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php new file mode 100644 index 0000000000000..2e34bcf7ab698 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php @@ -0,0 +1,210 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Customer\Test\Unit\ViewModel\Customer; + +use Magento\Customer\Model\Config\Share as ConfigShare; +use Magento\Framework\App\Request\DataPersistorInterface; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\TestCase; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Customer\ViewModel\Customer\Store as CustomerStore; +use Magento\Store\Model\System\Store as SystemStore; +use Magento\Store\Model\Store; + +/** + * Test for customer's store view model + */ +class StoreTest extends TestCase +{ + /** @var ObjectManagerHelper */ + private $objectManagerHelper; + + /** + * @var CustomerStore + */ + private $customerStore; + + /** + * @var SystemStore + */ + private $systemStore; + + /** + * @var Store + */ + private $store; + + /** + * @var ConfigShare + */ + protected $configShare; + + /** + * @var StoreManagerInterface + */ + protected $storeManager; + + /** + * @var DataPersistorInterface + */ + private $dataPersistor; + + protected function setUp() + { + $this->systemStore = $this->createMock(SystemStore::class); + $this->store = $this->createMock(Store::class); + $this->configShare = $this->createMock(ConfigShare::class); + $this->storeManager = $this->createMock(StoreManagerInterface::class); + $this->dataPersistor = $this->createMock(DataPersistorInterface::class); + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->customerStore = $this->objectManagerHelper->getObject( + CustomerStore::class, + [ + 'systemStore' => $this->systemStore, + 'configShare' => $this->configShare, + 'storeManager' => $this->storeManager, + 'dataPersistor' => $this->dataPersistor + ] + ); + } + + /** + * Test that method return correct array of options + * + * @param array $options + * @param bool $isWebsiteScope + * @param bool $isCustomerDataInSession + * @dataProvider dataProviderOptionsArray + * @return void + */ + public function testToOptionArray(array $options, bool $isWebsiteScope, bool $isCustomerDataInSession): void + { + $this->configShare->method('isWebsiteScope') + ->willReturn($isWebsiteScope); + $this->store->method('getWebsiteId') + ->willReturn(1); + + if ($isCustomerDataInSession) { + $this->dataPersistor->method('get') + ->with('customer') + ->willReturn([ + 'account' => ['website_id' => '1'] + ]); + } else { + $this->storeManager->method('getDefaultStoreView') + ->willReturn($this->store); + } + + $this->systemStore->method('getStoreData') + ->willReturn($this->store); + $this->systemStore->method('getStoreValuesForForm') + ->willReturn([ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + ] + ], + '__disableTmpl' => true, + ] + ]); + + $this->assertEquals($options, $this->customerStore->toOptionArray()); + } + + /** + * Data provider for testToOptionArray test + * + * @return array + */ + public function dataProviderOptionsArray(): array + { + return [ + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => true, + 'isCustomerDataInSession' => false, + ], + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => false, + 'isCustomerDataInSession' => false, + ], + [ + 'options' => [ + [ + 'label' => 'Main Website', + 'value' => [], + '__disableTmpl' => true, + 'website_id' => '1', + ], + [ + 'label' => 'Main Website', + 'value' => [ + [ + 'label' => '    Default Store View', + 'value' => '1', + 'website_id' => '1', + ] + ], + '__disableTmpl' => true, + 'website_id' => '1', + ] + ], + 'isWebsiteScope' => false, + 'isCustomerDataInSession' => true, + ] + ]; + } +} diff --git a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php index cb66dc3db7c77..a69e84ab41a2c 100644 --- a/app/code/Magento/Customer/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Customer/Ui/Component/ColumnFactory.php @@ -130,8 +130,6 @@ protected function getJsComponent($dataType) */ protected function getDataType($frontendType) { - return isset($this->dataTypeMap[$frontendType]) - ? $this->dataTypeMap[$frontendType] - : $this->dataTypeMap['default']; + return $this->dataTypeMap[$frontendType] ?? $this->dataTypeMap['default']; } } diff --git a/app/code/Magento/Customer/Ui/Component/FilterFactory.php b/app/code/Magento/Customer/Ui/Component/FilterFactory.php index 9bf07b877cc07..3e57db06246d4 100644 --- a/app/code/Magento/Customer/Ui/Component/FilterFactory.php +++ b/app/code/Magento/Customer/Ui/Component/FilterFactory.php @@ -76,6 +76,6 @@ public function create(array $attributeData, $context) */ protected function getFilterType($frontendInput) { - return isset($this->filterMap[$frontendInput]) ? $this->filterMap[$frontendInput] : $this->filterMap['default']; + return $this->filterMap[$frontendInput] ?? $this->filterMap['default']; } } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index eb8359de93f32..0a89cb6ea1449 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -14,7 +14,7 @@ use Magento\Customer\Model\Indexer\Attribute\Filter; /** - * Class AttributeRepository + * Attribute Repository Managment */ class AttributeRepository { @@ -156,10 +156,10 @@ protected function getOptionArray(array $options) * Return customer group's metadata by given group code * * @param string $code - * @return [] + * @return array | null */ public function getMetadataByCode($code) { - return isset($this->getList()[$code]) ? $this->getList()[$code] : null; + return $this->getList()[$code] ?? null; } } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php index 6befec8e942a1..346f6bdad43bd 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/ValidationRules.php @@ -63,9 +63,7 @@ public function getValidationRules($isRequired, $validationRules) protected function getValidationClass(ValidationRuleInterface $rule) { $key = $rule->getName() == 'input_validation' ? $rule->getValue() : $rule->getName(); - return isset($this->inputValidationMap[$key]) - ? $this->inputValidationMap[$key] - : $key; + return $this->inputValidationMap[$key] ?? $key; } /** diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index 70f8d085cc5ea..9bc164d7904d1 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -12,6 +12,9 @@ use Magento\Customer\Ui\Component\Listing\Column\InlineEditUpdater; use Magento\Customer\Api\CustomerMetadataInterface; +/** + * Columns component + */ class Columns extends \Magento\Ui\Component\Listing\Columns { /** @@ -29,6 +32,11 @@ class Columns extends \Magento\Ui\Component\Listing\Columns */ protected $inlineEditUpdater; + /** + * @var ColumnFactory + */ + private $columnFactory; + /** * @var array */ @@ -63,6 +71,8 @@ public function __construct( } /** + * Return default sort order + * * @return int */ protected function getDefaultSortOrder() @@ -94,7 +104,7 @@ protected function updateActionColumnSortOrder() } /** - * {@inheritdoc} + * @inheritdoc */ public function prepare() { @@ -113,6 +123,8 @@ public function prepare() } /** + * Add column to the component + * * @param array $attributeData * @param string $columnName * @return void @@ -129,6 +141,8 @@ public function addColumn(array $attributeData, $columnName) } /** + * Update column in component + * * @param array $attributeData * @param string $newAttributeCode * @return void @@ -200,6 +214,6 @@ public function addOptions(UiComponentInterface $component, array $attributeData */ protected function getFilterType($frontendInput) { - return isset($this->filterMap[$frontendInput]) ? $this->filterMap[$frontendInput] : $this->filterMap['default']; + return $this->filterMap[$frontendInput] ?? $this->filterMap['default']; } } diff --git a/app/code/Magento/Customer/ViewModel/Customer/Store.php b/app/code/Magento/Customer/ViewModel/Customer/Store.php new file mode 100644 index 0000000000000..1e6ca69e2d77a --- /dev/null +++ b/app/code/Magento/Customer/ViewModel/Customer/Store.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Customer\ViewModel\Customer; + +use Magento\Customer\Model\Config\Share as ConfigShare; +use Magento\Framework\App\Request\DataPersistorInterface; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Model\System\Store as SystemStore; + +/** + * Customer's store view model + */ +class Store implements OptionSourceInterface +{ + /** + * @var SystemStore + */ + private $systemStore; + + /** + * @var ConfigShare + */ + private $configShare; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var DataPersistorInterface + */ + private $dataPersistor; + + /** + * Store constructor. + * + * @param SystemStore $systemStore + * @param ConfigShare $configShare + * @param StoreManagerInterface $storeManager + * @param DataPersistorInterface $dataPersistor + */ + public function __construct( + SystemStore $systemStore, + ConfigShare $configShare, + StoreManagerInterface $storeManager, + DataPersistorInterface $dataPersistor + ) { + $this->systemStore = $systemStore; + $this->configShare = $configShare; + $this->storeManager = $storeManager; + $this->dataPersistor = $dataPersistor; + } + + /** + * @inheritdoc + */ + public function toOptionArray(): array + { + return (bool)$this->configShare->isWebsiteScope() ? $this->getStoreOptions() + : $this->getStoreOptionsWithCurrentWebsiteId(); + } + + /** + * Adding website ID to options list + * + * @return array + */ + private function getStoreOptions(): array + { + $options = $this->systemStore->getStoreValuesForForm(); + + $websiteKey = null; + foreach ($options as $key => $option) { + if ($websiteKey === null) { + $websiteKey = $key; + } + if (is_array($option['value']) && !empty($option['value'])) { + $websiteId = null; + foreach ($option['value'] as $storeViewKey => $storeView) { + $websiteId = $this->systemStore->getStoreData($storeView['value'])->getWebsiteId(); + $options[$key]['value'][$storeViewKey]['website_id'] = $websiteId; + } + if ($websiteId) { + $options[$key]['website_id'] = $websiteId; + if ($websiteKey !== null) { + $options[$websiteKey]['website_id'] = $websiteId; + $websiteKey = null; + } + } + } + } + + return $options; + } + + /** + * Adding current website ID to options list + * + * @return array + */ + private function getStoreOptionsWithCurrentWebsiteId(): array + { + $options = $this->systemStore->getStoreValuesForForm(); + + if (!empty($this->dataPersistor->get('customer')['account'])) { + $currentWebsiteId = (string)$this->dataPersistor->get('customer')['account']['website_id']; + } else { + $currentWebsiteId = $this->storeManager->getDefaultStoreView()->getWebsiteId(); + } + + foreach ($options as $key => $option) { + $options[$key]['website_id'] = $currentWebsiteId; + if (is_array($option['value']) && !empty($option['value'])) { + foreach ($option['value'] as $storeViewKey => $storeView) { + $storeView['website_id'] = $currentWebsiteId; + $options[$key]['value'][$storeViewKey] = $storeView; + } + } + } + + return $options; + } +} diff --git a/app/code/Magento/Customer/etc/frontend/sections.xml b/app/code/Magento/Customer/etc/frontend/sections.xml index 7938f28590ca8..e6a45dfdeaa49 100644 --- a/app/code/Magento/Customer/etc/frontend/sections.xml +++ b/app/code/Magento/Customer/etc/frontend/sections.xml @@ -7,10 +7,18 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"> - <action name="customer/account/logout"/> - <action name="customer/account/loginPost"/> - <action name="customer/account/createPost"/> - <action name="customer/account/editPost"/> + <action name="customer/account/logout"> + <section name="*"/> + </action> + <action name="customer/account/loginPost"> + <section name="*"/> + </action> + <action name="customer/account/createPost"> + <section name="*"/> + </action> + <action name="customer/account/editPost"> + <section name="*"/> + </action> <action name="customer/ajax/login"> <section name="checkout-data"/> <section name="cart"/> diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index f1b82bd5a4395..bb6c4b10bf75e 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -539,3 +539,5 @@ Addresses,Addresses "Middle Name/Initial","Middle Name/Initial" "Suffix","Suffix" "The Date of Birth should not be greater than today.","The Date of Birth should not be greater than today." +"The store view is not in the associated website.","The store view is not in the associated website." +"The Store View selected for sending Welcome email from is not related to the customer's associated website.","The Store View selected for sending Welcome email from is not related to the customer's associated website." diff --git a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_address_form.xml b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_address_form.xml index 3af0172b3fca8..517d8151b5f10 100644 --- a/app/code/Magento/Customer/view/adminhtml/ui_component/customer_address_form.xml +++ b/app/code/Magento/Customer/view/adminhtml/ui_component/customer_address_form.xml @@ -174,17 +174,7 @@ <label translate="true">Company</label> </settings> </field> - <field name="city" sortOrder="80" formElement="input"> - <settings> - <dataType>text</dataType> - <label translate="true">City</label> - <visible>true</visible> - <validation> - <rule name="required-entry" xsi:type="boolean">true</rule> - </validation> - </settings> - </field> - <field name="country_id" component="Magento_Customer/js/form/element/country" sortOrder="90" formElement="select"> + <field name="country_id" component="Magento_Customer/js/form/element/country" sortOrder="80" formElement="select"> <settings> <validation> <rule name="required-entry" xsi:type="boolean">true</rule> @@ -212,6 +202,16 @@ </select> </formElements> </field> + <field name="city" sortOrder="100" formElement="input"> + <settings> + <dataType>text</dataType> + <label translate="true">City</label> + <visible>true</visible> + <validation> + <rule name="required-entry" xsi:type="boolean">true</rule> + </validation> + </settings> + </field> <field name="postcode" component="Magento_Ui/js/form/element/post-code" sortOrder="120" formElement="input"> <settings> <dataType>text</dataType> diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml index 7caaeab4f39d6..d5c7154a30f54 100644 --- a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -301,7 +301,7 @@ <visible>true</visible> </settings> </field> - <field name="sendemail_store_id" formElement="select"> + <field name="sendemail_store_id" component="Magento_Ui/js/form/element/select" formElement="select"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="source" xsi:type="string">customer</item> @@ -317,7 +317,11 @@ <formElements> <select> <settings> - <options class="Magento\Store\Model\System\Store"/> + <options class="Magento\Customer\ViewModel\Customer\Store"/> + <filterBy> + <field>website_id</field> + <target>${ $.provider }:${ $.parentScope }.website_id</target> + </filterBy> </settings> </select> </formElements> diff --git a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml index 1d940296f334a..e7519c7c3320b 100644 --- a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml @@ -6,6 +6,7 @@ /** @var \Magento\Customer\Block\Address\Edit $block */ /** @var \Magento\Customer\ViewModel\Address $viewModel */ +/** @var \Magento\Framework\Escaper $escaper */ $viewModel = $block->getViewModel(); ?> <?php $_company = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Company::class) ?> @@ -26,16 +27,16 @@ $viewModel = $block->getViewModel(); <?php $_streetValidationClassNotRequired = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> <?php $_regionValidationClass = $viewModel->addressGetAttributeValidationClass('region'); ?> <form class="form-address-edit" - action="<?= $block->escapeUrl($block->getSaveUrl()) ?>" + action="<?= $escaper->escapeUrl($block->getSaveUrl()) ?>" method="post" id="form-validate" enctype="multipart/form-data" - data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>"> + data-hasrequired="<?= $escaper->escapeHtmlAttr(__('* Required Fields')) ?>"> <fieldset class="fieldset"> - <legend class="legend"><span><?= $block->escapeHtml(__('Contact Information')) ?></span></legend><br> + <legend class="legend"><span><?= $escaper->escapeHtml(__('Contact Information')) ?></span></legend><br> <?= $block->getBlockHtml('formkey') ?> - <input type="hidden" name="success_url" value="<?= $block->escapeUrl($block->getSuccessUrl()) ?>"> - <input type="hidden" name="error_url" value="<?= $block->escapeUrl($block->getErrorUrl()) ?>"> + <input type="hidden" name="success_url" value="<?= $escaper->escapeUrl($block->getSuccessUrl()) ?>"> + <input type="hidden" name="error_url" value="<?= $escaper->escapeUrl($block->getErrorUrl()) ?>"> <?= $block->getNameBlockHtml() ?> <?php if ($_company->isEnabled()): ?> @@ -52,29 +53,29 @@ $viewModel = $block->getViewModel(); </fieldset> <fieldset class="fieldset"> - <legend class="legend"><span><?= $block->escapeHtml(__('Address')) ?></span></legend><br> + <legend class="legend"><span><?= $escaper->escapeHtml(__('Address')) ?></span></legend><br> <div class="field street required"> <label for="street_1" class="label"><span><?= /* @noEscape */ $_street ?></span></label> <div class="control"> <input type="text" name="street[]" - value="<?= $block->escapeHtmlAttr($block->getStreetLine(1)) ?>" + value="<?= $escaper->escapeHtmlAttr($block->getStreetLine(1)) ?>" title="<?= /* @noEscape */ $_street ?>" id="street_1" - class="input-text <?= $block->escapeHtmlAttr($_streetValidationClass) ?>"/> + class="input-text <?= $escaper->escapeHtmlAttr($_streetValidationClass) ?>"/> <div class="nested"> <?php for ($_i = 1, $_n = $viewModel->addressGetStreetLines(); $_i < $_n; $_i++): ?> <div class="field additional"> <label class="label" for="street_<?= /* @noEscape */ $_i + 1 ?>"> - <span><?= $block->escapeHtml(__('Street Address %1', $_i + 1)) ?></span> + <span><?= $escaper->escapeHtml(__('Street Address %1', $_i + 1)) ?></span> </label> <div class="control"> <input type="text" name="street[]" - value="<?= $block->escapeHtmlAttr($block->getStreetLine($_i + 1)) ?>" - title="<?= $block->escapeHtmlAttr(__('Street Address %1', $_i + 1)) ?>" + value="<?= $escaper->escapeHtmlAttr($block->getStreetLine($_i + 1)) ?>" + title="<?= $escaper->escapeHtmlAttr(__('Street Address %1', $_i + 1)) ?>" id="street_<?= /* @noEscape */ $_i + 1 ?>" class="input-text - <?= $block->escapeHtmlAttr($_streetValidationClassNotRequired) ?>"> + <?= $escaper->escapeHtmlAttr($_streetValidationClassNotRequired) ?>"> </div> </div> <?php endfor; ?> @@ -90,22 +91,19 @@ $viewModel = $block->getViewModel(); <div class="control"> <input type="text" name="vat_id" - value="<?= $block->escapeHtmlAttr($block->getAddress()->getVatId()) ?>" + value="<?= $escaper->escapeHtmlAttr($block->getAddress()->getVatId()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('vat_id') ?>" - class="input-text <?= $block->escapeHtmlAttr($_vatidValidationClass) ?>" + class="input-text <?= $escaper->escapeHtmlAttr($_vatidValidationClass) ?>" id="vat_id"> </div> </div> <?php endif; ?> - <div class="field city required"> - <label class="label" for="city"><span><?= /* @noEscape */ $_city ?></span></label> + <div class="field country required"> + <label class="label" for="country"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('country_id') ?></span> + </label> <div class="control"> - <input type="text" - name="city" - value="<?= $block->escapeHtmlAttr($block->getAddress()->getCity()) ?>" - title="<?= $block->escapeHtmlAttr(__('City')) ?>" - class="input-text <?= $block->escapeHtmlAttr($_cityValidationClass) ?>" - id="city"> + <?= $block->getCountryHtmlSelect() ?> </div> </div> <div class="field region required"> @@ -117,18 +115,31 @@ $viewModel = $block->getViewModel(); title="<?= /* @noEscape */ $_region ?>" class="validate-select region_id" <?= /* @noEscape */ !$_displayAll ? ' disabled="disabled"' : '' ?>> - <option value=""><?= $block->escapeHtml(__($_selectRegion)) ?></option> + <option value=""><?= $escaper->escapeHtml(__($_selectRegion)) ?></option> </select> <input type="text" id="region" name="region" - value="<?= $block->escapeHtmlAttr($block->getRegion()) ?>" + value="<?= $escaper->escapeHtmlAttr($block->getRegion()) ?>" title="<?= /* @noEscape */ $_region ?>" class="input-text validate-not-number-first - <?= $block->escapeHtmlAttr($_regionValidationClass) ?>" + <?= $escaper->escapeHtmlAttr($_regionValidationClass) ?>" <?= !$_displayAll ? ' disabled="disabled"' : '' ?>/> </div> </div> + <div class="field city required"> + <label class="label" for="city"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?></span> + </label> + <div class="control"> + <input type="text" + name="city" + value="<?= $escaper->escapeHtmlAttr($block->getAddress()->getCity()) ?>" + title="<?= $escaper->escapeHtmlAttr(__('City')) ?>" + class="input-text <?= $escaper->escapeHtmlAttr($_cityValidationClass) ?>" + id="city"> + </div> + </div> <div class="field zip required"> <label class="label" for="zip"> <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?></span> @@ -136,32 +147,26 @@ $viewModel = $block->getViewModel(); <div class="control"> <input type="text" name="postcode" - value="<?= $block->escapeHtmlAttr($block->getAddress()->getPostcode()) ?>" + value="<?= $escaper->escapeHtmlAttr($block->getAddress()->getPostcode()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" id="zip" class="input-text validate-zip-international - <?= $block->escapeHtmlAttr($_postcodeValidationClass) ?>"> + <?= $escaper->escapeHtmlAttr($_postcodeValidationClass) ?>"> <div role="alert" class="message warning" style="display:none"> <span></span> </div> </div> </div> - <div class="field country required"> - <label class="label" for="country"><span><?= /* @noEscape */ $_country_id ?></span></label> - <div class="control"> - <?= $block->getCountryHtmlSelect() ?> - </div> - </div> <?php if ($block->isDefaultBilling()): ?> <div class="message info"> - <span><?= $block->escapeHtml(__("It's a default billing address.")) ?></span> + <span><?= $escaper->escapeHtml(__("It's a default billing address.")) ?></span> </div> <?php elseif ($block->canSetAsDefaultBilling()): ?> <div class="field choice set billing"> <input type="checkbox" id="primary_billing" name="default_billing" value="1" class="checkbox"> <label class="label" for="primary_billing"> - <span><?= $block->escapeHtml(__('Use as my default billing address')) ?></span> + <span><?= $escaper->escapeHtml(__('Use as my default billing address')) ?></span> </label> </div> <?php else: ?> @@ -170,13 +175,13 @@ $viewModel = $block->getViewModel(); <?php if ($block->isDefaultShipping()): ?> <div class="message info"> - <span><?= $block->escapeHtml(__("It's a default shipping address.")) ?></span> + <span><?= $escaper->escapeHtml(__("It's a default shipping address.")) ?></span> </div> <?php elseif ($block->canSetAsDefaultShipping()): ?> <div class="field choice set shipping"> <input type="checkbox" id="primary_shipping" name="default_shipping" value="1" class="checkbox"> <label class="label" for="primary_shipping"> - <span><?= $block->escapeHtml(__('Use as my default shipping address')) ?></span> + <span><?= $escaper->escapeHtml(__('Use as my default shipping address')) ?></span> </label> </div> <?php else: ?> @@ -188,13 +193,13 @@ $viewModel = $block->getViewModel(); <button type="submit" class="action save primary" data-action="save-address" - title="<?= $block->escapeHtmlAttr(__('Save Address')) ?>"> - <span><?= $block->escapeHtml(__('Save Address')) ?></span> + title="<?= $escaper->escapeHtmlAttr(__('Save Address')) ?>"> + <span><?= $escaper->escapeHtml(__('Save Address')) ?></span> </button> </div> <div class="secondary"> - <a class="action back" href="<?= $block->escapeUrl($block->getBackUrl()) ?>"> - <span><?= $block->escapeHtml(__('Go back')) ?></span> + <a class="action back" href="<?= $escaper->escapeUrl($block->getBackUrl()) ?>"> + <span><?= $escaper->escapeHtml(__('Go back')) ?></span> </a> </div> </div> @@ -203,7 +208,7 @@ $viewModel = $block->getViewModel(); { "#form-validate": { "addressValidation": { - "postCodes": <?= /* @noEscape */ $block->getPostCodeConfig()->getSerializedPostCodes(); ?> + "postCodes": <?= /* @noEscape */ $block->getPostCodeConfig()->getSerializedPostCodes() ?> } }, "#country": { diff --git a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml index e2b6792439576..89b86f8af8e55 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml @@ -4,56 +4,81 @@ * See COPYING.txt for license details. */ +use Magento\Customer\Block\Widget\Name; + /** @var \Magento\Customer\Block\Form\Edit $block */ ?> -<form class="form form-edit-account" action="<?= $block->escapeUrl($block->getUrl('customer/account/editPost')) ?>" method="post" id="form-validate" enctype="multipart/form-data" data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>" autocomplete="off"> +<form class="form form-edit-account" + action="<?= $block->escapeUrl($block->getUrl('customer/account/editPost')) ?>" + method="post" id="form-validate" + enctype="multipart/form-data" + data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>" + autocomplete="off"> <fieldset class="fieldset info"> <?= $block->getBlockHtml('formkey') ?> <legend class="legend"><span><?= $block->escapeHtml(__('Account Information')) ?></span></legend><br> - <?= $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Name::class)->setObject($block->getCustomer())->toHtml() ?> + <?= $block->getLayout()->createBlock(Name::class)->setObject($block->getCustomer())->toHtml() ?> <?php $_dob = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Dob::class) ?> <?php $_taxvat = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Taxvat::class) ?> <?php $_gender = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Gender::class) ?> - <?php if ($_dob->isEnabled()) : ?> + <?php if ($_dob->isEnabled()): ?> <?= $_dob->setDate($block->getCustomer()->getDob())->toHtml() ?> <?php endif ?> - <?php if ($_taxvat->isEnabled()) : ?> + <?php if ($_taxvat->isEnabled()): ?> <?= $_taxvat->setTaxvat($block->getCustomer()->getTaxvat())->toHtml() ?> <?php endif ?> - <?php if ($_gender->isEnabled()) : ?> + <?php if ($_gender->isEnabled()): ?> <?= $_gender->setGender($block->getCustomer()->getGender())->toHtml() ?> <?php endif ?> <div class="field choice"> - <input type="checkbox" name="change_email" id="change-email" data-role="change-email" value="1" title="<?= $block->escapeHtmlAttr(__('Change Email')) ?>" class="checkbox" /> - <label class="label" for="change-email"><span><?= $block->escapeHtml(__('Change Email')) ?></span></label> + <input type="checkbox" name="change_email" id="change-email" data-role="change-email" value="1" + title="<?= $block->escapeHtmlAttr(__('Change Email')) ?>" class="checkbox" /> + <label class="label" for="change-email"> + <span><?= $block->escapeHtml(__('Change Email')) ?></span> + </label> </div> <div class="field choice"> - <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" title="<?= $block->escapeHtmlAttr(__('Change Password')) ?>"<?php if ($block->getChangePassword()) : ?> checked="checked"<?php endif; ?> class="checkbox" /> - <label class="label" for="change-password"><span><?= $block->escapeHtml(__('Change Password')) ?></span></label> + <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" + title="<?= $block->escapeHtmlAttr(__('Change Password')) ?>" + <?php if ($block->getChangePassword()): ?> checked="checked"<?php endif; ?> class="checkbox" /> + <label class="label" for="change-password"> + <span><?= $block->escapeHtml(__('Change Password')) ?></span> + </label> </div> </fieldset> <fieldset class="fieldset password" data-container="change-email-password"> - <legend class="legend"><span data-title="change-email-password"><?= $block->escapeHtml(__('Change Email and Password')) ?></span></legend><br> + <legend class="legend"> + <span data-title="change-email-password"><?= $block->escapeHtml(__('Change Email and Password')) ?></span> + </legend><br> <div class="field email required" data-container="change-email"> <label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label> <div class="control"> - <input type="email" name="email" id="email" autocomplete="email" data-input="change-email" value="<?= $block->escapeHtmlAttr($block->getCustomer()->getEmail()) ?>" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" class="input-text" data-validate="{required:true, 'validate-email':true}" /> + <input type="email" name="email" id="email" autocomplete="email" data-input="change-email" + value="<?= $block->escapeHtmlAttr($block->getCustomer()->getEmail()) ?>" + title="<?= $block->escapeHtmlAttr(__('Email')) ?>" + class="input-text" + data-validate="{required:true, 'validate-email':true}" /> </div> </div> <div class="field password current required"> - <label class="label" for="current-password"><span><?= $block->escapeHtml(__('Current Password')) ?></span></label> + <label class="label" for="current-password"> + <span><?= $block->escapeHtml(__('Current Password')) ?></span> + </label> <div class="control"> - <input type="password" class="input-text" name="current_password" id="current-password" data-input="current-password" autocomplete="off" /> + <input type="password" class="input-text" name="current_password" id="current-password" + data-input="current-password" + autocomplete="off" /> </div> </div> <div class="field new password required" data-container="new-password"> <label class="label" for="password"><span><?= $block->escapeHtml(__('New Password')) ?></span></label> <div class="control"> + <?php $minCharacterSets = $block->getRequiredCharacterClassesNumber() ?> <input type="password" class="input-text" name="password" id="password" data-password-min-length="<?= $block->escapeHtml($block->getMinimumPasswordLength()) ?>" - data-password-min-character-sets="<?= $block->escapeHtml($block->getRequiredCharacterClassesNumber()) ?>" + data-password-min-character-sets="<?= $block->escapeHtml($minCharacterSets) ?>" data-input="new-password" data-validate="{required:true, 'validate-customer-password':true}" autocomplete="off" /> @@ -68,7 +93,9 @@ </div> </div> <div class="field confirmation password required" data-container="confirm-password"> - <label class="label" for="password-confirmation"><span><?= $block->escapeHtml(__('Confirm New Password')) ?></span></label> + <label class="label" for="password-confirmation"> + <span><?= $block->escapeHtml(__('Confirm New Password')) ?></span> + </label> <div class="control"> <input type="password" class="input-text" name="password_confirmation" id="password-confirmation" data-input="confirm-password" @@ -79,10 +106,14 @@ <?= $block->getChildHtml('form_additional_info') ?> <div class="actions-toolbar"> <div class="primary"> - <button type="submit" class="action save primary" title="<?= $block->escapeHtmlAttr(__('Save')) ?>"><span><?= $block->escapeHtml(__('Save')) ?></span></button> + <button type="submit" class="action save primary" title="<?= $block->escapeHtmlAttr(__('Save')) ?>"> + <span><?= $block->escapeHtml(__('Save')) ?></span> + </button> </div> <div class="secondary"> - <a class="action back" href="<?= $block->escapeUrl($block->getBackUrl()) ?>"><span><?= $block->escapeHtml(__('Go back')) ?></span></a> + <a class="action back" href="<?= $block->escapeUrl($block->getBackUrl()) ?>"> + <span><?= $block->escapeHtml(__('Go back')) ?></span> + </a> </div> </div> </form> @@ -95,7 +126,7 @@ var ignore = <?= /* @noEscape */ $_dob->isEnabled() ? '\'input[id$="full"]\'' : 'null' ?>; dataForm.mage('validation', { - <?php if ($_dob->isEnabled()) : ?> + <?php if ($_dob->isEnabled()): ?> errorPlacement: function(error, element) { if (element.prop('id').search('full') !== -1) { var dobElement = $(element).parents('.customer-dob'), @@ -109,20 +140,21 @@ } }, ignore: ':hidden:not(' + ignore + ')' - <?php else : ?> + <?php else: ?> ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' <?php endif ?> }); }); </script> +<?php $changeEmailAndPasswordTitle = $block->escapeHtml(__('Change Email and Password')) ?> <script type="text/x-magento-init"> { "[data-role=change-email], [data-role=change-password]": { "changeEmailPassword": { "titleChangeEmail": "<?= $block->escapeJs($block->escapeHtml(__('Change Email'))) ?>", "titleChangePassword": "<?= $block->escapeJs($block->escapeHtml(__('Change Password'))) ?>", - "titleChangeEmailAndPassword": "<?= $block->escapeJs($block->escapeHtml(__('Change Email and Password'))) ?>" + "titleChangeEmailAndPassword": "<?= $block->escapeJs($changeEmailAndPasswordTitle) ?>" } }, "[data-container=new-password]": { diff --git a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml index da0bb6e4cbc8b..6a267c9996908 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -3,78 +3,123 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:disable Magento2.Templates.ThisInTemplate.FoundHelper +// phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis + +use Magento\Customer\Helper\Address; /** @var \Magento\Customer\Block\Form\Register $block */ +/** @var \Magento\Framework\Escaper $escaper */ +$formData = $block->getFormData(); ?> +<?php $displayAll = $block->getConfig('general/region/display_all'); ?> <?= $block->getChildHtml('form_fields_before') ?> <?php /* Extensions placeholder */ ?> <?= $block->getChildHtml('customer.form.register.extra') ?> -<form class="form create account form-create-account" action="<?= $block->escapeUrl($block->getPostActionUrl()) ?>" method="post" id="form-validate" enctype="multipart/form-data" autocomplete="off"> - <?= /* @noEscape */ $block->getBlockHtml('formkey'); ?> +<form class="form create account form-create-account" + action="<?= $escaper->escapeUrl($block->getPostActionUrl()) ?>" + method="post" + id="form-validate" + enctype="multipart/form-data" + autocomplete="off"> + <?= /* @noEscape */ $block->getBlockHtml('formkey') ?> <fieldset class="fieldset create info"> - <legend class="legend"><span><?= $block->escapeHtml(__('Personal Information')) ?></span></legend><br> - <input type="hidden" name="success_url" value="<?= $block->escapeUrl($block->getSuccessUrl()) ?>"> - <input type="hidden" name="error_url" value="<?= $block->escapeUrl($block->getErrorUrl()) ?>"> - <?= $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Name::class)->setObject($block->getFormData())->setForceUseCustomerAttributes(true)->toHtml() ?> - <?php if ($block->isNewsletterEnabled()) : ?> + <legend class="legend"><span><?= $escaper->escapeHtml(__('Personal Information')) ?></span></legend><br> + <input type="hidden" name="success_url" value="<?= $escaper->escapeUrl($block->getSuccessUrl()) ?>"> + <input type="hidden" name="error_url" value="<?= $escaper->escapeUrl($block->getErrorUrl()) ?>"> + <?= $block->getLayout() + ->createBlock(\Magento\Customer\Block\Widget\Name::class) + ->setObject($formData) + ->setForceUseCustomerAttributes(true) + ->toHtml() ?> + <?php if ($block->isNewsletterEnabled()): ?> <div class="field choice newsletter"> - <input type="checkbox" name="is_subscribed" title="<?= $block->escapeHtmlAttr(__('Sign Up for Newsletter')) ?>" value="1" id="is_subscribed"<?php if ($block->getFormData()->getIsSubscribed()) : ?> checked="checked"<?php endif; ?> class="checkbox"> - <label for="is_subscribed" class="label"><span><?= $block->escapeHtml(__('Sign Up for Newsletter')) ?></span></label> + <input type="checkbox" + name="is_subscribed" + title="<?= $escaper->escapeHtmlAttr(__('Sign Up for Newsletter')) ?>" + value="1" + id="is_subscribed" + <?php if ($formData->getIsSubscribed()): ?>checked="checked"<?php endif; ?> + class="checkbox"> + <label for="is_subscribed" class="label"> + <span><?= $escaper->escapeHtml(__('Sign Up for Newsletter')) ?></span> + </label> </div> <?php /* Extensions placeholder */ ?> <?= $block->getChildHtml('customer.form.register.newsletter') ?> <?php endif ?> <?php $_dob = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Dob::class) ?> - <?php if ($_dob->isEnabled()) : ?> - <?= $_dob->setDate($block->getFormData()->getDob())->toHtml() ?> + <?php if ($_dob->isEnabled()): ?> + <?= $_dob->setDate($formData->getDob())->toHtml() ?> <?php endif ?> <?php $_taxvat = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Taxvat::class) ?> - <?php if ($_taxvat->isEnabled()) : ?> - <?= $_taxvat->setTaxvat($block->getFormData()->getTaxvat())->toHtml() ?> + <?php if ($_taxvat->isEnabled()): ?> + <?= $_taxvat->setTaxvat($formData->getTaxvat())->toHtml() ?> <?php endif ?> <?php $_gender = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Gender::class) ?> - <?php if ($_gender->isEnabled()) : ?> - <?= $_gender->setGender($block->getFormData()->getGender())->toHtml() ?> + <?php if ($_gender->isEnabled()): ?> + <?= $_gender->setGender($formData->getGender())->toHtml() ?> <?php endif ?> </fieldset> - <?php if ($block->getShowAddressFields()) : ?> + <?php if ($block->getShowAddressFields()): ?> + <?php $cityValidationClass = $this->helper(Address::class)->getAttributeValidationClass('city'); ?> + <?php $postcodeValidationClass = $this->helper(Address::class)->getAttributeValidationClass('postcode'); ?> + <?php $regionValidationClass = $this->helper(Address::class)->getAttributeValidationClass('region'); ?> <fieldset class="fieldset address"> - <legend class="legend"><span><?= $block->escapeHtml(__('Address Information')) ?></span></legend><br> + <legend class="legend"><span><?= $escaper->escapeHtml(__('Address Information')) ?></span></legend><br> <input type="hidden" name="create_address" value="1" /> <?php $_company = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Company::class) ?> - <?php if ($_company->isEnabled()) : ?> - <?= $_company->setCompany($block->getFormData()->getCompany())->toHtml() ?> + <?php if ($_company->isEnabled()): ?> + <?= $_company->setCompany($formData->getCompany())->toHtml() ?> <?php endif ?> <?php $_telephone = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Telephone::class) ?> - <?php if ($_telephone->isEnabled()) : ?> - <?= $_telephone->setTelephone($block->getFormData()->getTelephone())->toHtml() ?> + <?php if ($_telephone->isEnabled()): ?> + <?= $_telephone->setTelephone($formData->getTelephone())->toHtml() ?> <?php endif ?> <?php $_fax = $block->getLayout()->createBlock(\Magento\Customer\Block\Widget\Fax::class) ?> - <?php if ($_fax->isEnabled()) : ?> - <?= $_fax->setFax($block->getFormData()->getFax())->toHtml() ?> + <?php if ($_fax->isEnabled()): ?> + <?= $_fax->setFax($formData->getFax())->toHtml() ?> <?php endif ?> - <?php $_streetValidationClass = $this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('street'); ?> + <?php + $_streetValidationClass = $this->helper(Address::class) + ->getAttributeValidationClass('street'); + ?> <div class="field street required"> - <label for="street_1" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?></span></label> + <label for="street_1" class="label"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?></span> + </label> <div class="control"> - <input type="text" name="street[]" value="<?= $block->escapeHtmlAttr($block->getFormData()->getStreet(0)) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?>" id="street_1" class="input-text <?= $block->escapeHtmlAttr($_streetValidationClass) ?>"> + <input type="text" + name="street[]" + value="<?= $escaper->escapeHtmlAttr($formData->getStreet(0)) ?>" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('street') ?>" + id="street_1" + class="input-text <?= $escaper->escapeHtmlAttr($_streetValidationClass) ?>"> <div class="nested"> - <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> - <?php for ($_i = 2, $_n = $this->helper(\Magento\Customer\Helper\Address::class)->getStreetLines(); $_i <= $_n; $_i++) : ?> + <?php + $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); + $streetLines = $this->helper(Address::class)->getStreetLines(); + ?> + <?php for ($_i = 2, $_n = $streetLines; $_i <= $_n; $_i++): ?> <div class="field additional"> <label class="label" for="street_<?= /* @noEscape */ $_i ?>"> - <span><?= $block->escapeHtml(__('Address')) ?></span> + <span><?= $escaper->escapeHtml(__('Address')) ?></span> </label> <div class="control"> - <input type="text" name="street[]" value="<?= $block->escapeHtml($block->getFormData()->getStreetLine($_i - 1)) ?>" title="<?= $block->escapeHtmlAttr(__('Street Address %1', $_i)) ?>" id="street_<?= /* @noEscape */ $_i ?>" class="input-text <?= $block->escapeHtmlAttr($_streetValidationClass) ?>"> + <input type="text" + name="street[]" + value="<?= $escaper->escapeHtml($formData->getStreetLine($_i - 1)) ?>" + title="<?= $escaper->escapeHtmlAttr(__('Street Address %1', $_i)) ?>" + id="street_<?= /* @noEscape */ $_i ?>" + class="input-text <?= $escaper->escapeHtmlAttr($_streetValidationClass) ?>"> </div> </div> <?php endfor; ?> @@ -82,38 +127,70 @@ </div> </div> - <div class="field required"> - <label for="city" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?></span></label> + <div class="field country required"> + <label for="country" class="label"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('country_id') ?></span> + </label> <div class="control"> - <input type="text" name="city" value="<?= $block->escapeHtmlAttr($block->getFormData()->getCity()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('city')) ?>" id="city"> + <?= $block->getCountryHtmlSelect() ?> </div> </div> <div class="field region required"> - <label for="region_id" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?></span></label> + <label for="region_id" class="label"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?></span> + </label> <div class="control"> - <select id="region_id" name="region_id" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" class="validate-select region_id" style="display:none;"> - <option value=""><?= $block->escapeHtml(__('Please select a region, state or province.')) ?></option> + <select id="region_id" + name="region_id" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" + class="validate-select region_id" + style="display: none;"> + <option value=""> + <?= $escaper->escapeHtml(__('Please select a region, state or province.')) ?> + </option> </select> - <input type="text" id="region" name="region" value="<?= $block->escapeHtml($block->getRegion()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" class="input-text <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('region')) ?>" style="display:none;"> + <input type="text" + id="region" + name="region" + value="<?= $escaper->escapeHtml($block->getRegion()) ?>" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('region') ?>" + class="input-text <?= $escaper->escapeHtmlAttr($regionValidationClass) ?>" + style="display:none;"> </div> </div> - <div class="field zip required"> - <label for="zip" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?></span></label> + <div class="field required"> + <label for="city" class="label"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?></span> + </label> <div class="control"> - <input type="text" name="postcode" value="<?= $block->escapeHtmlAttr($block->getFormData()->getPostcode()) ?>" title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" id="zip" class="input-text validate-zip-international <?= $block->escapeHtmlAttr($this->helper(\Magento\Customer\Helper\Address::class)->getAttributeValidationClass('postcode')) ?>"> + <input type="text" + name="city" + value="<?= $escaper->escapeHtmlAttr($formData->getCity()) ?>" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('city') ?>" + class="input-text <?= $escaper->escapeHtmlAttr($cityValidationClass) ?>" + id="city"> </div> </div> - <div class="field country required"> - <label for="country" class="label"><span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('country_id') ?></span></label> + <div class="field zip required"> + <label for="zip" class="label"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?></span> + </label> <div class="control"> - <?= $block->getCountryHtmlSelect() ?> + <input type="text" + name="postcode" + value="<?= $escaper->escapeHtmlAttr($formData->getPostcode()) ?>" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('postcode') ?>" + id="zip" + class="input-text validate-zip-international + <?= $escaper->escapeHtmlAttr($postcodeValidationClass) ?>"> </div> </div> + <?php $addressAttributes = $block->getChildBlock('customer_form_address_user_attributes');?> - <?php if ($addressAttributes) : ?> + <?php if ($addressAttributes): ?> <?php $addressAttributes->setEntityType('customer_address'); ?> <?php $addressAttributes->setFieldIdFormat('address:%1$s')->setFieldNameFormat('address[%1$s]');?> <?php $block->restoreSessionData($addressAttributes->getMetadataForm(), 'address');?> @@ -124,29 +201,40 @@ </fieldset> <?php endif; ?> - <fieldset class="fieldset create account" data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>"> - <legend class="legend"><span><?= $block->escapeHtml(__('Sign-in Information')) ?></span></legend><br> + <fieldset class="fieldset create account" + data-hasrequired="<?= $escaper->escapeHtmlAttr(__('* Required Fields')) ?>"> + <legend class="legend"><span><?= $escaper->escapeHtml(__('Sign-in Information')) ?></span></legend><br> <div class="field required"> - <label for="email_address" class="label"><span><?= $block->escapeHtml(__('Email')) ?></span></label> + <label for="email_address" class="label"><span><?= $escaper->escapeHtml(__('Email')) ?></span></label> <div class="control"> - <input type="email" name="email" autocomplete="email" id="email_address" value="<?= $block->escapeHtmlAttr($block->getFormData()->getEmail()) ?>" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" class="input-text" data-mage-init='{"mage/trim-input":{}}' data-validate="{required:true, 'validate-email':true}"> + <input type="email" + name="email" + autocomplete="email" + id="email_address" + value="<?= $escaper->escapeHtmlAttr($formData->getEmail()) ?>" + title="<?= $escaper->escapeHtmlAttr(__('Email')) ?>" + class="input-text" + data-mage-init='{"mage/trim-input":{}}' + data-validate="{required:true, 'validate-email':true}"> </div> </div> <div class="field password required"> - <label for="password" class="label"><span><?= $block->escapeHtml(__('Password')) ?></span></label> + <label for="password" class="label"><span><?= $escaper->escapeHtml(__('Password')) ?></span></label> <div class="control"> <input type="password" name="password" id="password" - title="<?= $block->escapeHtmlAttr(__('Password')) ?>" + title="<?= $escaper->escapeHtmlAttr(__('Password')) ?>" class="input-text" - data-password-min-length="<?= $block->escapeHtmlAttr($block->getMinimumPasswordLength()) ?>" - data-password-min-character-sets="<?= $block->escapeHtmlAttr($block->getRequiredCharacterClassesNumber()) ?>" + data-password-min-length="<?= + $escaper->escapeHtmlAttr($block->getMinimumPasswordLength()) ?>" + data-password-min-character-sets="<?= + $escaper->escapeHtmlAttr($block->getRequiredCharacterClassesNumber()) ?>" data-validate="{required:true, 'validate-customer-password':true}" autocomplete="off"> <div id="password-strength-meter-container" data-role="password-strength-meter" aria-live="polite"> <div id="password-strength-meter" class="password-strength-meter"> - <?= $block->escapeHtml(__('Password Strength')) ?>: + <?= $escaper->escapeHtml(__('Password Strength')) ?>: <span id="password-strength-meter-label" data-role="password-strength-meter-label"> - <?= $block->escapeHtml(__('No Password')) ?> + <?= $escaper->escapeHtml(__('No Password')) ?> </span> </div> </div> @@ -154,19 +242,34 @@ </div> <div class="field confirmation required"> - <label for="password-confirmation" class="label"><span><?= $block->escapeHtml(__('Confirm Password')) ?></span></label> + <label for="password-confirmation" class="label"> + <span><?= $escaper->escapeHtml(__('Confirm Password')) ?></span> + </label> <div class="control"> - <input type="password" name="password_confirmation" title="<?= $block->escapeHtmlAttr(__('Confirm Password')) ?>" id="password-confirmation" class="input-text" data-validate="{required:true, equalTo:'#password'}" autocomplete="off"> + <input type="password" + name="password_confirmation" + title="<?= $escaper->escapeHtmlAttr(__('Confirm Password')) ?>" + id="password-confirmation" + class="input-text" + data-validate="{required:true, equalTo:'#password'}" + autocomplete="off"> </div> </div> <?= $block->getChildHtml('form_additional_info') ?> </fieldset> <div class="actions-toolbar"> <div class="primary"> - <button type="submit" class="action submit primary" title="<?= $block->escapeHtmlAttr(__('Create an Account')) ?>"><span><?= $block->escapeHtml(__('Create an Account')) ?></span></button> + <button type="submit" + class="action submit primary" + title="<?= $escaper->escapeHtmlAttr(__('Create an Account')) ?>"> + <span><?= $escaper->escapeHtml(__('Create an Account')) ?></span> + </button> </div> <div class="secondary"> - <a class="action back" href="<?= $block->escapeUrl($block->getBackUrl()) ?>"><span><?= $block->escapeHtml(__('Back')) ?></span></a> + <a class="action back" + href="<?= $escaper->escapeUrl($block->getBackUrl()) ?>"> + <span><?= $escaper->escapeHtml(__('Back')) ?></span> + </a> </div> </div> </form> @@ -180,7 +283,7 @@ require([ var ignore = <?= /* @noEscape */ $_dob->isEnabled() ? '\'input[id$="full"]\'' : 'null' ?>; dataForm.mage('validation', { - <?php if ($_dob->isEnabled()) : ?> + <?php if ($_dob->isEnabled()): ?> errorPlacement: function(error, element) { if (element.prop('id').search('full') !== -1) { var dobElement = $(element).parents('.customer-dob'), @@ -194,26 +297,28 @@ require([ } }, ignore: ':hidden:not(' + ignore + ')' - <?php else : ?> + <?php else: ?> ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' <?php endif ?> }).find('input:text').attr('autocomplete', 'off'); }); </script> -<?php if ($block->getShowAddressFields()) : ?> +<?php if ($block->getShowAddressFields()): ?> <script type="text/x-magento-init"> { "#country": { "regionUpdater": { - "optionalRegionAllowed": <?= /* @noEscape */ $block->getConfig('general/region/display_all') ? 'true' : 'false' ?>, + "optionalRegionAllowed": <?= /* @noEscape */ $displayAll ? 'true' : 'false' ?>, "regionListId": "#region_id", "regionInputId": "#region", "postcodeId": "#zip", "form": "#form-validate", - "regionJson": <?= /* @noEscape */ $this->helper(\Magento\Directory\Helper\Data::class)->getRegionJson() ?>, - "defaultRegion": "<?= (int) $block->getFormData()->getRegionId() ?>", - "countriesWithOptionalZip": <?= /* @noEscape */ $this->helper(\Magento\Directory\Helper\Data::class)->getCountriesWithOptionalZip(true) ?> + "regionJson": <?= /* @noEscape */ $this->helper(\Magento\Directory\Helper\Data::class) + ->getRegionJson() ?>, + "defaultRegion": "<?= (int) $formData->getRegionId() ?>", + "countriesWithOptionalZip": <?= /* @noEscape */ $this->helper(\Magento\Directory\Helper\Data::class) + ->getCountriesWithOptionalZip(true) ?> } } } diff --git a/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml b/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml index 4c3432233189b..eb460e69118a9 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml @@ -14,7 +14,7 @@ </span> </label> <div class="control"> - <input type="text" + <input type="tel" name="telephone" id="telephone" value="<?= $block->escapeHtmlAttr($block->getTelephone()) ?>" diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index 55c58282bcae4..4eee5a39d55e1 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -480,7 +480,7 @@ public function prepareCustomerData($rows): void $ids = []; foreach ($customersPresent as $customerData) { - $id = $this->getCustomerStorage()->getCustomerId( + $id = $this->getCustomerStorage()->getLoadedCustomerId( $customerData['email'], $customerData['website_id'] ); @@ -606,9 +606,10 @@ protected function _prepareDataForUpdate(array $rowData): array $newAddress = true; // get address id if ($rowData[self::COLUMN_ADDRESS_ID] + && $customerId && $this->addressStorage->doesExist( - $rowData[self::COLUMN_ADDRESS_ID], - (string)$customerId + (int) $rowData[self::COLUMN_ADDRESS_ID], + $customerId ) ) { $newAddress = false; @@ -856,7 +857,7 @@ protected function _validateRowForUpdate(array $rowData, $rowNumber) if ($this->_checkUniqueKey($rowData, $rowNumber)) { $email = strtolower($rowData[self::COLUMN_EMAIL]); $website = $rowData[self::COLUMN_WEBSITE]; - $addressId = $rowData[self::COLUMN_ADDRESS_ID]; + $addressId = (int) $rowData[self::COLUMN_ADDRESS_ID]; $customerId = $this->_getCustomerId($email, $website); if ($customerId === false) { @@ -925,16 +926,16 @@ protected function _validateRowForDelete(array $rowData, $rowNumber) if ($this->_checkUniqueKey($rowData, $rowNumber)) { $email = strtolower($rowData[self::COLUMN_EMAIL]); $website = $rowData[self::COLUMN_WEBSITE]; - $addressId = $rowData[self::COLUMN_ADDRESS_ID]; + $addressId = (int) $rowData[self::COLUMN_ADDRESS_ID]; $customerId = $this->_getCustomerId($email, $website); if ($customerId === false) { $this->addRowError(self::ERROR_CUSTOMER_NOT_FOUND, $rowNumber); - } elseif (!strlen($addressId)) { + } elseif (!$addressId) { $this->addRowError(self::ERROR_ADDRESS_ID_IS_EMPTY, $rowNumber); } elseif (!$this->addressStorage->doesExist( - (string)$addressId, - (string)$customerId + $addressId, + $customerId )) { $this->addRowError(self::ERROR_ADDRESS_NOT_FOUND, $rowNumber); } @@ -948,11 +949,11 @@ protected function _validateRowForDelete(array $rowData, $rowNumber) * @param int $addressId * @return bool */ - protected function _checkRowDuplicate($customerId, $addressId) + protected function _checkRowDuplicate(int $customerId, int $addressId) { $isAddressExists = $this->addressStorage->doesExist( - (string)$addressId, - (string)$customerId + $addressId, + $customerId ); $isPkRowSet = isset($this->_importedRowPks[$customerId][$addressId]); diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index 0f4c5f82bfe1d..4a22dc83a1f31 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -6,6 +6,7 @@ namespace Magento\CustomerImportExport\Model\Import; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; +use Magento\Customer\Model\Indexer\Processor; /** * Import entity customer combined model @@ -148,6 +149,11 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit */ protected $masterAttributeCode = 'email'; + /** + * @var Processor + */ + private $indexerProcessor; + /** * @param \Magento\Framework\Stdlib\StringUtils $string * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig @@ -158,6 +164,7 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit * @param \Magento\CustomerImportExport\Model\ResourceModel\Import\CustomerComposite\DataFactory $dataFactory * @param \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory * @param \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory + * @param Processor $indexerProcessor * @param array $data * @throws \Magento\Framework\Exception\LocalizedException * @@ -173,6 +180,7 @@ public function __construct( \Magento\CustomerImportExport\Model\ResourceModel\Import\CustomerComposite\DataFactory $dataFactory, \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory, \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory, + Processor $indexerProcessor, array $data = [] ) { parent::__construct($string, $scopeConfig, $importFactory, $resourceHelper, $resource, $errorAggregator, $data); @@ -230,6 +238,7 @@ public function __construct( } else { $this->_nextCustomerId = $resourceHelper->getNextAutoincrement($this->_customerEntity->getEntityTable()); } + $this->indexerProcessor = $indexerProcessor; } /** @@ -273,11 +282,12 @@ protected function _importData() $this->countItemsCreated += $this->_customerEntity->getCreatedItemsCount(); $this->countItemsUpdated += $this->_customerEntity->getUpdatedItemsCount(); $this->countItemsDeleted += $this->_customerEntity->getDeletedItemsCount(); - if ($this->getBehavior() != \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE) { - return $result && $this->_addressEntity->setCustomerAttributes($this->_customerAttributes)->importData(); + $result = $result && $this->_addressEntity->setCustomerAttributes($this->_customerAttributes)->importData(); + } + if ($result) { + $this->indexerProcessor->markIndexerAsInvalid(); } - return $result; } diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php index 6d29d7ae792ff..f722aef3239bf 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php @@ -23,7 +23,7 @@ class Storage /** * IDs of addresses grouped by customer IDs. * - * @var string[][] + * @var int[][] */ private $addresses = []; @@ -62,16 +62,16 @@ public function __construct( /** * Record existing address. * - * @param string $customerId - * @param string $addressId - * + * @param int $customerId + * @param int $addressId * @return void */ - private function addRecord(string $customerId, string $addressId): void + private function addRecord(int $customerId, int $addressId): void { if (!$customerId || !$addressId) { return; } + if (!array_key_exists($customerId, $this->addresses)) { $this->addresses[$customerId] = []; } @@ -84,7 +84,7 @@ private function addRecord(string $customerId, string $addressId): void /** * Load addresses IDs for given customers. * - * @param string[] $customerIds + * @param int[] $customerIds * * @return void */ @@ -95,27 +95,31 @@ private function loadAddresses(array $customerIds): void $collection->removeAttributeToSelect(); $select = $collection->getSelect(); $tableId = array_keys($select->getPart(Select::FROM))[0]; - $select->where($tableId .'.parent_id in (?)', $customerIds); + $select->reset(Select::COLUMNS)->columns([$tableId . '.entity_id', $tableId . '.parent_id']); - $this->collectionIterator->iterate( - $collection, - $this->config->getValue(AbstractEntity::XML_PATH_PAGE_SIZE), - [ - function (DataObject $record) { - $this->addRecord($record->getParentId(), $record->getId()); - } - ] - ); + $pageSize = $this->config->getValue(AbstractEntity::XML_PATH_PAGE_SIZE); + $getChuck = function (int $offset) use ($customerIds, $pageSize) { + return array_slice($customerIds, $offset, $pageSize); + }; + $offset = 0; + for ($idsChunk = $getChuck($offset); !empty($idsChunk); $offset += $pageSize, $idsChunk = $getChuck($offset)) { + $chunkSelect = clone $select; + $chunkSelect->where($tableId .'.parent_id IN (?)', $idsChunk); + $addresses = $collection->getConnection()->fetchAll($chunkSelect); + foreach ($addresses as $address) { + $this->addRecord((int) $address['parent_id'], (int) $address['entity_id']); + } + } } /** * Check if given address exists for given customer. * - * @param string $addressId - * @param string $forCustomerId + * @param int $addressId + * @param int $forCustomerId * @return bool */ - public function doesExist(string $addressId, string $forCustomerId): bool + public function doesExist(int $addressId, int $forCustomerId): bool { return array_key_exists($forCustomerId, $this->addresses) && in_array( @@ -128,7 +132,7 @@ public function doesExist(string $addressId, string $forCustomerId): bool /** * Pre-load addresses for given customers. * - * @param string[] $forCustomersIds + * @param int[] $forCustomersIds * @return void */ public function prepareAddresses(array $forCustomersIds): void @@ -138,13 +142,7 @@ public function prepareAddresses(array $forCustomersIds): void } $forCustomersIds = array_unique($forCustomersIds); - $customerIdsToUse = []; - foreach ($forCustomersIds as $customerId) { - if (!array_key_exists((string)$customerId, $this->addresses)) { - $customerIdsToUse[] = $customerId; - } - } - + $customerIdsToUse = array_diff($forCustomersIds, array_keys($this->addresses)); $this->loadAddresses($customerIdsToUse); } } diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php index 7cff2dcc21b1e..11f326e6dfc8f 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php @@ -9,8 +9,6 @@ use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory as CustomerCollectionFactory; use Magento\Framework\DataObject; use Magento\Framework\DB\Select; -use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIterator; -use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory; /** * Storage to check existing customers. @@ -38,13 +36,6 @@ class Storage */ protected $_pageSize; - /** - * Collection by pages iterator. - * - * @var CollectionByPagesIterator - */ - protected $_byPagesIterator; - /** * @var CustomerCollectionFactory */ @@ -71,65 +62,47 @@ class Storage /** * @param CustomerCollectionFactory $collectionFactory - * @param CollectionByPagesIteratorFactory $colIteratorFactory * @param array $data */ public function __construct( CustomerCollectionFactory $collectionFactory, - CollectionByPagesIteratorFactory $colIteratorFactory, array $data = [] ) { $this->_customerCollection = isset( $data['customer_collection'] ) ? $data['customer_collection'] : $collectionFactory->create(); - $this->_pageSize = isset($data['page_size']) ? $data['page_size'] : 0; - $this->_byPagesIterator = isset( - $data['collection_by_pages_iterator'] - ) ? $data['collection_by_pages_iterator'] : $colIteratorFactory->create(); + $this->_pageSize = isset($data['page_size']) ? (int) $data['page_size'] : 0; $this->customerCollectionFactory = $collectionFactory; } /** - * Create new collection to load customer data with proper filters. + * Load customer's data that can be found by given identifiers. * - * @param array[] $customerIdentifiers With keys "email" and "website_id". - * - * @return CustomerCollection + * @param array $customerIdentifiers With keys "email" and "website_id". + * @return void */ - private function prepareCollection(array $customerIdentifiers): CustomerCollection + private function loadCustomersData(array $customerIdentifiers): void { /** @var CustomerCollection $collection */ $collection = $this->customerCollectionFactory->create(); $collection->removeAttributeToSelect(); $select = $collection->getSelect(); $customerTableId = array_keys($select->getPart(Select::FROM))[0]; - $select->where( - $customerTableId . '.email in (?)', - array_map( - function (array $customer) { - return $customer['email']; - }, - $customerIdentifiers - ) - ); - return $collection; - } - - /** - * Load customers' data that can be found by given identifiers. - * - * @param array $customerIdentifiers With keys "email" and "website_id". - * - * @return void - */ - private function loadCustomersData(array $customerIdentifiers) - { - $this->_byPagesIterator->iterate( - $this->prepareCollection($customerIdentifiers), - $this->_pageSize, - [[$this, 'addCustomer']] - ); + $pageSize = $this->_pageSize ?: count($customerIdentifiers); + $getChuck = function (int $offset) use ($customerIdentifiers, $pageSize) { + return array_slice($customerIdentifiers, $offset, $pageSize); + }; + $offset = 0; + for ($chunk = $getChuck($offset); !empty($chunk); $offset += $pageSize, $chunk = $getChuck($offset)) { + $emails = array_column($chunk, 'email'); + $chunkSelect = clone $select; + $chunkSelect->where($customerTableId . '.email IN (?)', $emails); + $customers = $collection->getConnection()->fetchAll($chunkSelect); + foreach ($customers as $customer) { + $this->addCustomerByArray($customer); + } + } } /** @@ -147,8 +120,9 @@ public function addCustomerByArray(array $customer): Storage if (!isset($this->customerStoreIds[$email])) { $this->customerStoreIds[$email] = []; } - $this->_customerIds[$email][$customer['website_id']] = $customer['entity_id']; - $this->customerStoreIds[$email][$customer['website_id']] = $customer['store_id'] ?? null; + $websiteId = (int) $customer['website_id']; + $this->_customerIds[$email][$websiteId] = (int) $customer['entity_id']; + $this->customerStoreIds[$email][$websiteId] = $customer['store_id'] ?? null; return $this; } @@ -190,6 +164,18 @@ public function getCustomerId(string $email, int $websiteId) return false; } + /** + * Get previously loaded customer id. + * + * @param string $email + * @param int $websiteId + * @return int|null + */ + public function getLoadedCustomerId(string $email, int $websiteId): ?int + { + return $this->_customerIds[mb_strtolower($email)][$websiteId] ?? null; + } + /** * Find customer store ID for unique pair of email and website ID. * diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php index 1b900c2139588..7aff0f911c2b0 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php @@ -15,7 +15,7 @@ use Magento\ImportExport\Model\Import\Source\Csv; /** - * Customer composite test + * The test for Customer composite model * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -88,6 +88,12 @@ class CustomerCompositeTest extends \PHPUnit\Framework\TestCase */ protected $errorFactory; + /** + * @var \Magento\Customer\Model\Indexer\Processor + * |\PHPUnit\Framework\MockObject\MockObject + */ + private $indexerProcessor; + /** * Expected prepared data after method CustomerComposite::_prepareRowForDb * @@ -141,6 +147,7 @@ protected function setUp() ->getMock(); $this->_scopeConfigMock = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); + $this->indexerProcessor = $this->createMock(\Magento\Customer\Model\Indexer\Processor::class); } /** @@ -159,6 +166,7 @@ protected function _createModelMock($data) $this->_dataFactory, $this->_customerFactory, $this->_addressFactory, + $this->indexerProcessor, $data ); } diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php deleted file mode 100644 index 1f2f9f3fed583..0000000000000 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/ResourceModel/Import/Customer/StorageTest.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * Test class for \Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\Storage - */ -namespace Magento\CustomerImportExport\Test\Unit\Model\ResourceModel\Import\Customer; - -use Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\Storage; -use Magento\Customer\Model\ResourceModel\Customer\Collection; -use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory; -use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory; -use Magento\Framework\DataObject; -use Magento\Framework\DB\Select; -use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIterator; - -class StorageTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var Storage - */ - private $model; - - /** - * @var CollectionByPagesIterator|\PHPUnit_Framework_MockObject_MockObject - */ - private $iteratorMock; - - /** - * @var Collection|\PHPUnit_Framework_MockObject_MockObject - */ - private $collectionMock; - - protected function setUp() - { - $this->iteratorMock = $this->createMock( - CollectionByPagesIterator::class - ); - /** @var \PHPUnit_Framework_MockObject_MockObject|CollectionByPagesIteratorFactory $iteratorFactoryMock */ - $iteratorFactoryMock = $this->createMock( - CollectionByPagesIteratorFactory::class - ); - $iteratorFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->iteratorMock); - $this->collectionMock = $this->createMock(Collection::class); - /** @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject $collectionFactoryMock */ - $collectionFactoryMock = $this->createMock( - CollectionFactory::class - ); - $collectionFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->collectionMock); - /** @var \PHPUnit_Framework_MockObject_MockObject $selectMock */ - $selectMock = $this->createMock(Select::class); - $selectMock->expects($this->any()) - ->method('getPart') - ->with(Select::FROM) - ->willReturn(['e' => []]); - $this->collectionMock->expects($this->any()) - ->method('getSelect') - ->willReturn($selectMock); - - $this->model = new Storage( - $collectionFactoryMock, - $iteratorFactoryMock, - [] - ); - } - - protected function tearDown() - { - unset($this->model); - } - - public function testAddCustomerByArray() - { - $propertyName = '_customerIds'; - $customer = $this->_addCustomerToStorage(); - - $this->assertAttributeCount(1, $propertyName, $this->model); - $expectedCustomerData = [$customer['website_id'] => $customer['entity_id']]; - $this->assertAttributeContains($expectedCustomerData, $propertyName, $this->model); - } - - public function testGetCustomerId() - { - $existingEmail = 'test@magento.com'; - $existingWebsiteId = 0; - $existingId = 1; - $nonExistingEmail = 'test1@magento.com'; - $nonExistingWebsiteId = 2; - - $this->iteratorMock->expects($this->at(0)) - ->method('iterate') - ->willReturnCallback( - function (...$args) use ( - $existingId, - $existingEmail, - $existingWebsiteId - ) { - /** @var callable $callable */ - foreach ($args[2] as $callable) { - $callable( - new DataObject([ - 'id' => $existingId, - 'email' => $existingEmail, - 'website_id' => $existingWebsiteId, - ]) - ); - } - } - ); - $this->assertEquals( - $existingId, - $this->model->getCustomerId($existingEmail, $existingWebsiteId) - ); - $this->assertFalse( - $this->model->getCustomerId( - $nonExistingEmail, - $nonExistingWebsiteId - ) - ); - } - - /** - * @return array - */ - protected function _addCustomerToStorage() - { - $customer = ['entity_id' => 1, 'website_id' => 1, 'email' => 'test@test.com']; - $this->model->addCustomerByArray($customer); - - return $customer; - } -} diff --git a/app/code/Magento/Deploy/Model/Mode.php b/app/code/Magento/Deploy/Model/Mode.php index fe24fb297e978..0d97042af460b 100644 --- a/app/code/Magento/Deploy/Model/Mode.php +++ b/app/code/Magento/Deploy/Model/Mode.php @@ -205,7 +205,7 @@ public function enableDefaultMode() public function getMode() { $env = $this->reader->load(); - return isset($env[State::PARAM_MODE]) ? $env[State::PARAM_MODE] : null; + return $env[State::PARAM_MODE] ?? null; } /** diff --git a/app/code/Magento/Deploy/Package/Package.php b/app/code/Magento/Deploy/Package/Package.php index 4821d32454675..2a83d0d4c56ec 100644 --- a/app/code/Magento/Deploy/Package/Package.php +++ b/app/code/Magento/Deploy/Package/Package.php @@ -219,7 +219,7 @@ public function isVirtual() */ public function getParam($name) { - return isset($this->params[$name]) ? $this->params[$name] : null; + return $this->params[$name] ?? null; } /** @@ -253,7 +253,7 @@ public function getThemeModel() */ public function getFile($fileId) { - return isset($this->files[$fileId]) ? $this->files[$fileId] : false; + return $this->files[$fileId] ?? false; } /** diff --git a/app/code/Magento/Deploy/Package/PackagePool.php b/app/code/Magento/Deploy/Package/PackagePool.php index b9c0418df860a..9057f50fb3c91 100644 --- a/app/code/Magento/Deploy/Package/PackagePool.php +++ b/app/code/Magento/Deploy/Package/PackagePool.php @@ -60,16 +60,20 @@ public function __construct( } /** + * Return package + * * @param string $path * @return Package|null */ public function getPackage($path) { $this->collect(); - return isset($this->packages[$path]) ? $this->packages[$path] : null; + return $this->packages[$path] ?? null; } /** + * Return packages + * * @return Package[] */ public function getPackages() @@ -79,6 +83,8 @@ public function getPackages() } /** + * Return theme model + * * @param string $areaCode * @param string $themePath * @return ThemeInterface|null @@ -93,6 +99,8 @@ public function getThemeModel($areaCode, $themePath) } /** + * Return packages from deployment + * * @param array $options * @return Package[] */ @@ -140,6 +148,8 @@ private function isAncestorForDeployedPackages(Package $excludedPackage, array $ } /** + * Return theme by full path + * * @param string $fullPath * @return ThemeInterface|null */ @@ -154,6 +164,8 @@ private function getThemeByFullPath($fullPath) } /** + * Collect packages + * * @param bool $recollect * @return void */ @@ -244,6 +256,8 @@ private function checkPackageSkip(Package $package, array $options) } /** + * Check if can deploy area + * * @param Package $package * @param array $options * @return bool @@ -264,6 +278,8 @@ private function canDeployArea(Package $package, array $options) } /** + * Verify can deploy theme + * * @param Package $package * @param array $options * @return bool @@ -281,6 +297,8 @@ private function canDeployTheme(Package $package, array $options) } /** + * Verify can deploy locale + * * @param Package $package * @param array $options * @return bool @@ -297,6 +315,8 @@ private function canDeployLocale(Package $package, array $options) } /** + * Check if included entity + * * @param string $entity * @param array $includedEntities * @param array $excludedEntities @@ -316,16 +336,20 @@ private function isIncluded($entity, array $includedEntities, array $excludedEnt } /** + * Return option by name + * * @param string $name * @param array $options * @return mixed|null */ private function getOption($name, $options) { - return isset($options[$name]) ? $options[$name] : null; + return $options[$name] ?? null; } /** + * Ensure package exist + * * @param array $params * @return void */ diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index b6333d6fec71e..6c8d804c61efe 100644 --- a/app/code/Magento/Deploy/Service/DeployStaticContent.php +++ b/app/code/Magento/Deploy/Service/DeployStaticContent.php @@ -156,7 +156,7 @@ public function deploy(array $options) */ private function getProcessesAmount(array $options) { - return isset($options[Options::JOBS_AMOUNT]) ? (int)$options[Options::JOBS_AMOUNT] : 0; + return (int)($options[Options::JOBS_AMOUNT] ?? 0); } /** diff --git a/app/code/Magento/Deploy/Source/SourcePool.php b/app/code/Magento/Deploy/Source/SourcePool.php index 3179a0a5c0aa3..2c391e78e94c8 100644 --- a/app/code/Magento/Deploy/Source/SourcePool.php +++ b/app/code/Magento/Deploy/Source/SourcePool.php @@ -44,6 +44,6 @@ public function getAll() */ public function getSource($name) { - return isset($this->sources[$name]) ? $this->sources[$name] : null; + return $this->sources[$name] ?? null; } } diff --git a/app/code/Magento/Dhl/Model/Carrier.php b/app/code/Magento/Dhl/Model/Carrier.php index ad76f5070b35b..6587b462099be 100644 --- a/app/code/Magento/Dhl/Model/Carrier.php +++ b/app/code/Magento/Dhl/Model/Carrier.php @@ -704,7 +704,7 @@ public function getDhlProductTitle($code) $contentType = $this->getConfigData('content_type'); $dhlProducts = $this->getDhlProducts($contentType); - return isset($dhlProducts[$code]) ? $dhlProducts[$code] : false; + return $dhlProducts[$code] ?? false; } /** @@ -1373,7 +1373,7 @@ protected function getCountryParams($countryCode) if (isset($this->_countryParams->{$countryCode})) { $countryParams = new \Magento\Framework\DataObject($this->_countryParams->{$countryCode}->asArray()); } - return isset($countryParams) ? $countryParams : new \Magento\Framework\DataObject(); + return $countryParams ?? new \Magento\Framework\DataObject(); } /** diff --git a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php index d1b35c8e2b77f..1b9d1619a8d4c 100644 --- a/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Dhl/Test/Unit/Model/CarrierTest.php @@ -187,7 +187,7 @@ public function scopeConfigGetValue($path) 'carriers/dhl/debug' => 1, 'shipping/origin/country_id' => 'GB' ]; - return isset($pathMap[$path]) ? $pathMap[$path] : null; + return $pathMap[$path] ?? null; } /** diff --git a/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml b/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml new file mode 100644 index 0000000000000..8b72e3e93efb9 --- /dev/null +++ b/app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AllowToChooseStateIfItIsOptionalForCountryEnabled"> + <data key="path">general/region/display_all</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="AllowToChooseStateIfItIsOptionalForCountryDisabled"> + <data key="path">general/region/display_all</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml b/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml index 853872dd907bd..51fd2facab3b0 100644 --- a/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml +++ b/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml @@ -12,7 +12,7 @@ <features value="Directory"/> <title value="Scheduled import settings hidden"/> <stories value="Fields visibility according to 'Enable' value"/> - <description value="Scheduled Import Settings' should hide fields when 'Enabled' is 'No'"/> + <description value="Scheduled Import Settings should hide fields when 'Enabled' is 'No'"/> <severity value="MINOR"/> </annotations> <before> @@ -21,7 +21,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set currency/import/enabled 0" stepKey="disableCurrencyImport"/> </after> diff --git a/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php b/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php new file mode 100644 index 0000000000000..9d38a2c72f3ac --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php @@ -0,0 +1,110 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Directory\Test\Unit\Block\Adminhtml\Frontend\Currency; + +use Magento\Directory\Block\Adminhtml\Frontend\Currency\Base; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Data\Form\Element\AbstractElement; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Directory\Block\Adminhtml\Frontend\Currency\Base + */ +class BaseTest extends TestCase +{ + const STUB_WEBSITE_PARAM = 'website'; + + /** + * @var AbstractElement|MockObject + */ + private $elementMock; + + /** + * @var RequestInterface|MockObject + */ + private $requestMock; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Base + */ + private $baseCurrency; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->elementMock = $this->createMock(AbstractElement::class); + $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + + $this->baseCurrency = (new ObjectManagerHelper($this))->getObject( + Base::class, + ['_request' => $this->requestMock, '_scopeConfig' => $this->scopeConfigMock] + ); + } + + /** + * Test case when no Website param provided + */ + public function testRenderWithoutWebsiteParam() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(''); + $this->scopeConfigMock->expects($this->never())->method('getValue'); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertFalse(empty($result), 'Result should not be empty.'); + } + + /** + * Test case when Website param is provided and Price Scope is set to Global + */ + public function testRenderWhenWebsiteParamSetAndPriceScopeGlobal() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(self::STUB_WEBSITE_PARAM); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->willReturn(Store::PRICE_SCOPE_GLOBAL); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertEquals('', $result, 'Result should be an empty string.'); + } + + /** + * Test case when Website param is provided and Price Scope is not Global + */ + public function testRenderWhenWebsiteParamSetAndPriceScopeOther() + { + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willReturn(self::STUB_WEBSITE_PARAM); + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->willReturn(Store::PRICE_SCOPE_WEBSITE); + + $result = $this->baseCurrency->render(($this->elementMock)); + $this->assertFalse(empty($result), 'Result should not be empty.'); + } +} diff --git a/app/code/Magento/Directory/etc/frontend/sections.xml b/app/code/Magento/Directory/etc/frontend/sections.xml index a2bc5696abf08..48d63ec82d95b 100644 --- a/app/code/Magento/Directory/etc/frontend/sections.xml +++ b/app/code/Magento/Directory/etc/frontend/sections.xml @@ -7,5 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"> - <action name="directory/currency/switch"/> + <action name="directory/currency/switch"> + <section name="*"/> + </action> </config> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateAndEditDownloadableProductSettingsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateAndEditDownloadableProductSettingsTest.xml index ebd36dddc0b6c..a09f205b8c4d0 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateAndEditDownloadableProductSettingsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateAndEditDownloadableProductSettingsTest.xml @@ -29,7 +29,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create new downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml index e0a38e7db7552..9a1f1273a41fd 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductAndAssignItToCustomStoreTest.xml @@ -41,7 +41,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteCreatedStoreView"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create store view --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml index fb5983bb58b6d..8e08ae813faed 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Downloadable product --> @@ -88,6 +88,8 @@ <!-- Save product --> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> + <!-- Go to storefront category page --> <amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/> <waitForPageLoad stepKey="waitForCategoryPageLoad"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml index 18dedca393178..865f392f7c841 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml @@ -40,7 +40,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml index 64920432f2e01..7fcb70b169ab7 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithGroupPriceTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml index 3b315d030cc8c..94753a1e5e2b3 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithLinkTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml index 5ab683034bad8..e9a6efc49b635 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithManageStockTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml index 3348603563ff1..16d88c16073cb 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithOutOfStockStatusTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml index 0ac14680cff46..307eb43273dbd 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithSpecialPriceTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml index c80c42bc53ed9..092129dc1ba1e 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutFillingQuantityAndStockTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml index 27a27f22c87ff..63796a197e586 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithoutTaxClassIdTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create downloadable product --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml index 0d93bac16569f..3d01168613ecc 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDeleteDownloadableProductTest.xml @@ -34,7 +34,7 @@ <after> <magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteDownloadableProductFilteredBySkuAndName"> <argument name="product" value="$$createDownloadableProduct$$"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml index a09076b7dc06e..27d505e070f5b 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml @@ -34,6 +34,8 @@ <argument name="product" value="DownloadableProduct"/> </actionGroup> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <!--See related product in storefront--> <amOnPage url="{{DownloadableProduct.sku}}.html" stepKey="goToStorefront"/> </test> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml index 4a13a3f60e385..f2b6dc9e8a809 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml @@ -50,7 +50,7 @@ <!--Delete product--> <comment userInput="Delete product" stepKey="commentDeleteProduct"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Change product type to Downloadable--> <comment userInput="Change product type to Downloadable" stepKey="commentCreateDownloadable"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/EditDownloadableProductWithSeparateLinksFromCartTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/EditDownloadableProductWithSeparateLinksFromCartTest.xml index 6535bf11d43c4..3d9229a4b0854 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/EditDownloadableProductWithSeparateLinksFromCartTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/EditDownloadableProductWithSeparateLinksFromCartTest.xml @@ -76,7 +76,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Step 1: Navigate to store front Product page as guest --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/ManualSelectAllDownloadableLinksDownloadableProductTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/ManualSelectAllDownloadableLinksDownloadableProductTest.xml index 3ab64be9ad2ca..7eea3926f450c 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/ManualSelectAllDownloadableLinksDownloadableProductTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/ManualSelectAllDownloadableLinksDownloadableProductTest.xml @@ -76,7 +76,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Step 1: Navigate to store front Product page as guest --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/SelectAllDownloadableLinksDownloadableProductTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/SelectAllDownloadableLinksDownloadableProductTest.xml index 3f77eff56193d..2ce0272852711 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/SelectAllDownloadableLinksDownloadableProductTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/SelectAllDownloadableLinksDownloadableProductTest.xml @@ -76,7 +76,7 @@ </actionGroup> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Step 1: Navigate to store front Product page as guest --> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/VerifyDisableDownloadableProductSamplesAreNotAccessibleTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/VerifyDisableDownloadableProductSamplesAreNotAccessibleTest.xml index b0f7edaeaa3a9..b641a2541ff98 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/VerifyDisableDownloadableProductSamplesAreNotAccessibleTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/VerifyDisableDownloadableProductSamplesAreNotAccessibleTest.xml @@ -53,7 +53,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Open Downloadable product from precondition on Storefront --> diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Sample/DeleteHandlerTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Sample/DeleteHandlerTest.php new file mode 100644 index 0000000000000..b633c843138c5 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Sample/DeleteHandlerTest.php @@ -0,0 +1,100 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Downloadable\Test\Unit\Model\Sample; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product; +use Magento\Downloadable\Api\Data\SampleInterface; +use Magento\Downloadable\Api\SampleRepositoryInterface as SampleRepository; +use Magento\Downloadable\Model\Product\Type; +use Magento\Downloadable\Model\Sample\DeleteHandler; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Downloadable\Model\Sample\DeleteHandler + */ +class DeleteHandlerTest extends TestCase +{ + const STUB_PRODUCT_TYPE = 'simple'; + const STUB_PRODUCT_SKU = 'sku'; + const STUB_SAMPLE_ID = 1; + + /** + * @var ProductInterface|MockObject + */ + private $entityMock; + + /** + * @var SampleRepository|MockObject + */ + private $sampleRepositoryMock; + + /** + * @var DeleteHandler + */ + private $deleteHandler; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->entityMock = $this->createMock(Product::class); + $this->sampleRepositoryMock = $this->getMockBuilder(SampleRepository::class) + ->disableOriginalConstructor() + ->setMethods(['getList', 'delete']) + ->getMockForAbstractClass(); + + $this->deleteHandler = (new ObjectManagerHelper($this))->getObject( + DeleteHandler::class, + ['sampleRepository' => $this->sampleRepositoryMock] + ); + } + + /** + * Test case when provided Product has type Downloadable. + */ + public function testExecuteWithDownloadableProduct() + { + $this->entityMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(Type::TYPE_DOWNLOADABLE); + $this->entityMock->expects($this->once()) + ->method('getSku') + ->willReturn(self::STUB_PRODUCT_SKU); + + $sampleMock = $this->createMock(SampleInterface::class); + $sampleMock->expects($this->once()) + ->method('getId') + ->willReturn(self::STUB_SAMPLE_ID); + + $this->sampleRepositoryMock->expects($this->once())->method('delete'); + $this->sampleRepositoryMock->expects($this->once()) + ->method('getList') + ->willReturn([$sampleMock]); + + $this->assertSame($this->entityMock, $this->deleteHandler->execute($this->entityMock)); + } + + /** + * Test case when provided Product is not Downloadable. + */ + public function testExecuteWithOtherProduct() + { + $this->entityMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(self::STUB_PRODUCT_TYPE); + + $this->sampleRepositoryMock->expects($this->never())->method('getList'); + $this->sampleRepositoryMock->expects($this->never())->method('delete'); + $this->assertSame($this->entityMock, $this->deleteHandler->execute($this->entityMock)); + } +} diff --git a/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php b/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php index c24f87d36d64b..8f0a3fb2baa69 100644 --- a/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php +++ b/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php @@ -11,6 +11,9 @@ use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Data\Collection\AbstractDb; +/** + * SearchCriteria FilterProcessor + */ class FilterProcessor implements CollectionProcessorInterface { /** @@ -113,6 +116,6 @@ private function getCustomFilterForField($field) */ private function getFieldMapping($field) { - return isset($this->fieldMapping[$field]) ? $this->fieldMapping[$field] : $field; + return $this->fieldMapping[$field] ?? $field; } } diff --git a/app/code/Magento/Eav/Model/Config.php b/app/code/Magento/Eav/Model/Config.php index 20126d5146c35..765403567b6d9 100644 --- a/app/code/Magento/Eav/Model/Config.php +++ b/app/code/Magento/Eav/Model/Config.php @@ -228,7 +228,7 @@ public function clear() */ protected function _load($id) { - return isset($this->_objects[$id]) ? $this->_objects[$id] : null; + return $this->_objects[$id] ?? null; } /** @@ -239,14 +239,14 @@ protected function _load($id) */ private function loadAttributes($entityTypeCode) { - return isset($this->attributes[$entityTypeCode]) ? $this->attributes[$entityTypeCode] : []; + return $this->attributes[$entityTypeCode] ?? []; } /** * Associate object with identifier * - * @param mixed $obj - * @param mixed $id + * @param mixed $obj + * @param mixed $id * @return void * @codeCoverageIgnore */ @@ -271,8 +271,8 @@ private function saveAttribute(AbstractAttribute $attribute, $entityTypeCode, $a /** * Specify reference for entity type id * - * @param int $id - * @param string $code + * @param int $id + * @param string $code * @return $this * @codeCoverageIgnore */ @@ -290,15 +290,15 @@ protected function _addEntityTypeReference($id, $code) */ protected function _getEntityTypeReference($id) { - return isset($this->_references['entity'][$id]) ? $this->_references['entity'][$id] : null; + return $this->_references['entity'][$id] ?? null; } /** * Specify reference between entity attribute id and attribute code * - * @param int $id - * @param string $code - * @param string $entityTypeCode + * @param int $id + * @param string $code + * @param string $entityTypeCode * @return $this */ protected function _addAttributeReference($id, $code, $entityTypeCode) @@ -522,9 +522,9 @@ public function getAttributes($entityType) /** * Get attribute by code for entity type * - * @param mixed $entityType - * @param mixed $code - * @return AbstractAttribute + * @param mixed $entityType + * @param mixed $code + * @return AbstractAttribute * @throws LocalizedException */ public function getAttribute($entityType, $code) @@ -737,8 +737,8 @@ public function getEntityAttributeCodes($entityType, $object = null) /** * Get all entity type attributes * - * @param int|string|Type $entityType - * @param \Magento\Framework\DataObject|null $object + * @param int|string|Type $entityType + * @param \Magento\Framework\DataObject|null $object * @return AbstractAttribute[] * * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -822,6 +822,10 @@ protected function _createAttribute($entityType, $attributeData) $fullAttributeData = array_key_exists('is_required', $attributeData); if ($existsFullAttribute || (!$existsFullAttribute && !$fullAttributeData)) { + $scopeIsRequired = $attributeData['scope_is_required'] ?? null; + if ($scopeIsRequired !== null) { + $attribute->setData('scope_is_required', $scopeIsRequired); + } return $attribute; } } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/Datetime.php b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/Datetime.php index ba6f6c6ea2aaa..6099d329571e8 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/Datetime.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/Datetime.php @@ -7,6 +7,8 @@ namespace Magento\Eav\Model\Entity\Attribute\Backend; /** + * Prepare date for save in DB + * * @api * @since 100.0.2 */ @@ -61,8 +63,8 @@ public function beforeSave($object) /** * Prepare date for save in DB * - * string format used from input fields (all date input fields need apply locale settings) - * int value can be declared in code (this meen whot we use valid date) + * String format is used in input fields (all date input fields need apply locale settings) + * int (Unix) format can be used in other parts of the code * * @param string|int|\DateTimeInterface $date * @return string @@ -72,7 +74,7 @@ public function formatDate($date) if (empty($date)) { return null; } - // unix timestamp given - simply instantiate date object + // Unix timestamp given - simply instantiate date object if (is_scalar($date) && preg_match('/^[0-9]+$/', $date)) { $date = (new \DateTime())->setTimestamp($date); } elseif (!($date instanceof \DateTimeInterface)) { diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php index dd4cd4217a127..23b6e8792100c 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/AbstractSource.php @@ -69,7 +69,7 @@ public function getOptionText($value) if (count($options) > 0) { foreach ($options as $option) { if (isset($option['value']) && $option['value'] == $value) { - return isset($option['label']) ? $option['label'] : $option['value']; + return $option['label'] ?? $option['value']; } } } diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index e50abbc11e54a..1fc513ed0ea80 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -24,7 +24,7 @@ abstract class AbstractCollection extends AbstractDb implements SourceProviderInterface { /** - * Attribute table alias prefix + * Define default prefix for attribute table alias */ const ATTRIBUTE_TABLE_ALIAS_PREFIX = 'at_'; @@ -495,7 +495,7 @@ public function addAttributeToSelect($attribute, $joinType = false) $entity = clone $this->getEntity(); $attributes = $entity->loadAllAttributes()->getAttributesByCode(); foreach ($attributes as $attrCode => $attr) { - $this->_selectAttributes[$attrCode] = $attr->getId(); + $this->_selectAttributes[$attrCode] = (int) $attr->getId(); } } else { if (isset($this->_joinAttributes[$attribute])) { @@ -511,7 +511,7 @@ public function addAttributeToSelect($attribute, $joinType = false) ) ); } - $this->_selectAttributes[$attrInstance->getAttributeCode()] = $attrInstance->getId(); + $this->_selectAttributes[$attrInstance->getAttributeCode()] = (int) $attrInstance->getId(); } return $this; } @@ -1173,7 +1173,7 @@ public function _loadAttributes($printQuery = false, $logQuery = false) } $attribute = $this->_eavConfig->getAttribute($entity->getType(), $attributeCode); if ($attribute && !$attribute->isStatic()) { - $tableAttributes[$attribute->getBackendTable()][] = $attributeId; + $tableAttributes[$attribute->getBackendTable()][] = (int) $attributeId; if (!isset($attributeTypes[$attribute->getBackendTable()])) { $attributeTypes[$attribute->getBackendTable()] = $attribute->getBackendType(); } diff --git a/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php b/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php index 87ff3a9d22bfd..fc775594c65fd 100644 --- a/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php +++ b/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php @@ -7,6 +7,9 @@ */ namespace Magento\Eav\Model\Entity\Setup; +/** + * @inheritdoc + */ abstract class PropertyMapperAbstract implements PropertyMapperInterface { /** @@ -22,6 +25,6 @@ protected function _getValue($array, $key, $default = null) if (isset($array[$key]) && is_bool($array[$key])) { $array[$key] = (int)$array[$key]; } - return isset($array[$key]) ? $array[$key] : $default; + return $array[$key] ?? $default; } } diff --git a/app/code/Magento/Eav/Model/Entity/Type.php b/app/code/Magento/Eav/Model/Entity/Type.php index 444d58bf546d4..24dbc0459ae97 100644 --- a/app/code/Magento/Eav/Model/Entity/Type.php +++ b/app/code/Magento/Eav/Model/Entity/Type.php @@ -264,7 +264,7 @@ public function fetchNewIncrementId($storeId = null) */ public function getEntityIdField() { - return isset($this->_data['entity_id_field']) ? $this->_data['entity_id_field'] : null; + return $this->_data['entity_id_field'] ?? null; } /** @@ -319,7 +319,7 @@ public function getEntityTablePrefix() */ public function getDefaultAttributeSetId() { - return isset($this->_data['default_attribute_set_id']) ? $this->_data['default_attribute_set_id'] : null; + return $this->_data['default_attribute_set_id'] ?? null; } /** @@ -329,7 +329,7 @@ public function getDefaultAttributeSetId() */ public function getEntityTypeId() { - return isset($this->_data['entity_type_id']) ? $this->_data['entity_type_id'] : null; + return $this->_data['entity_type_id'] ?? null; } /** @@ -339,7 +339,7 @@ public function getEntityTypeId() */ public function getEntityTypeCode() { - return isset($this->_data['entity_type_code']) ? $this->_data['entity_type_code'] : null; + return $this->_data['entity_type_code'] ?? null; } /** diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 73b0516117df6..eb9b173ed52be 100644 --- a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php +++ b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php @@ -6,9 +6,9 @@ namespace Magento\Eav\Model\TypeLocator; +use Magento\Eav\Api\AttributeRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Reflection\TypeProcessor; -use Magento\Eav\Api\AttributeRepositoryInterface; use Magento\Framework\Webapi\CustomAttribute\ServiceTypeListInterface; use Magento\Framework\Webapi\CustomAttributeTypeLocatorInterface; @@ -28,9 +28,10 @@ class SimpleType implements CustomAttributeTypeLocatorInterface private $serviceTypeList; /** - * Initialize dependencies. + * Constructor * * @param AttributeRepositoryInterface $attributeRepository + * @param ServiceTypeListInterface $serviceTypeList */ public function __construct( AttributeRepositoryInterface $attributeRepository, @@ -41,7 +42,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getType($attributeCode, $entityType) { @@ -59,12 +60,13 @@ public function getType($attributeCode, $entityType) 'datetime' => TypeProcessor::NORMALIZED_STRING_TYPE, 'decimal' => TypeProcessor::NORMALIZED_DOUBLE_TYPE, ]; - return isset($backendTypeMap[$backendType]) - ? $backendTypeMap[$backendType] : TypeProcessor::NORMALIZED_ANY_TYPE; + return $backendTypeMap[$backendType] ?? TypeProcessor::NORMALIZED_ANY_TYPE; } /** - * {@inheritDoc} + * Get data Types from service type list + * + * @return void */ public function getAllServiceDataInterfaces() { diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionStub.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionStub.php index 57374ed05618f..f82dbf0ee3dc9 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionStub.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionStub.php @@ -30,4 +30,14 @@ protected function _construct() { return $this->_init(\Magento\Framework\DataObject::class, 'test_entity_model'); } + + /** + * Retrieve collection empty item + * + * @return \Magento\Framework\DataObject + */ + public function getNewEmptyItem() + { + return new \Magento\Framework\DataObject(); + } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php index bc4ed7d4bd9e4..051c870a04b80 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php @@ -8,10 +8,15 @@ /** * AbstractCollection test * + * Test for AbstractCollection class * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AbstractCollectionTest extends \PHPUnit\Framework\TestCase { + const ATTRIBUTE_CODE = 'any_attribute'; + const ATTRIBUTE_ID_STRING = '15'; + const ATTRIBUTE_ID_INT = 15; + /** * @var AbstractCollectionStub|\PHPUnit_Framework_MockObject_MockObject */ @@ -105,6 +110,26 @@ protected function setUp() $entityMock = $this->createMock(\Magento\Eav\Model\Entity\AbstractEntity::class); $entityMock->expects($this->any())->method('getConnection')->will($this->returnValue($connectionMock)); $entityMock->expects($this->any())->method('getDefaultAttributes')->will($this->returnValue([])); + $entityMock->expects($this->any())->method('getLinkField')->willReturn('entity_id'); + + $attributeMock = $this->createMock(\Magento\Eav\Model\Attribute::class); + $attributeMock->expects($this->any())->method('isStatic')->willReturn(false); + $attributeMock->expects($this->any())->method('getAttributeCode')->willReturn(self::ATTRIBUTE_CODE); + $attributeMock->expects($this->any())->method('getBackendTable')->willReturn('eav_entity_int'); + $attributeMock->expects($this->any())->method('getBackendType')->willReturn('int'); + $attributeMock->expects($this->any())->method('getId')->willReturn(self::ATTRIBUTE_ID_STRING); + + $entityMock + ->expects($this->any()) + ->method('getAttribute') + ->with(self::ATTRIBUTE_CODE) + ->willReturn($attributeMock); + + $this->configMock + ->expects($this->any()) + ->method('getAttribute') + ->with(null, self::ATTRIBUTE_CODE) + ->willReturn($attributeMock); $this->validatorFactoryMock->expects( $this->any() @@ -193,6 +218,34 @@ public function testRemoveItemByKey($values, $count) $this->assertNull($this->model->getItemById($testId)); } + /** + * @dataProvider getItemsDataProvider + */ + public function testAttributeIdIsInt($values) + { + $this->resourceHelperMock->expects($this->any())->method('getLoadAttributesSelectGroups')->willReturn([]); + $this->fetchStrategyMock->expects($this->any())->method('fetchAll')->will($this->returnValue($values)); + $selectMock = $this->coreResourceMock->getConnection()->select(); + $selectMock->expects($this->any())->method('from')->willReturn($selectMock); + $selectMock->expects($this->any())->method('join')->willReturn($selectMock); + $selectMock->expects($this->any())->method('where')->willReturn($selectMock); + $selectMock->expects($this->any())->method('columns')->willReturn($selectMock); + + $this->model + ->addAttributeToSelect(self::ATTRIBUTE_CODE) + ->_loadEntities() + ->_loadAttributes(); + + $_selectAttributesActualValue = $this->readAttribute($this->model, '_selectAttributes'); + + $this->assertAttributeEquals( + [self::ATTRIBUTE_CODE => self::ATTRIBUTE_ID_STRING], + '_selectAttributes', + $this->model + ); + $this->assertSame($_selectAttributesActualValue[self::ATTRIBUTE_CODE], self::ATTRIBUTE_ID_INT); + } + /** * @return array */ diff --git a/app/code/Magento/Elasticsearch/Test/Mftf/Test/ProductQuickSearchUsingElasticSearchTest.xml b/app/code/Magento/Elasticsearch/Test/Mftf/Test/ProductQuickSearchUsingElasticSearchTest.xml index fb28e6dd4d9df..9fcc1909ab42c 100644 --- a/app/code/Magento/Elasticsearch/Test/Mftf/Test/ProductQuickSearchUsingElasticSearchTest.xml +++ b/app/code/Magento/Elasticsearch/Test/Mftf/Test/ProductQuickSearchUsingElasticSearchTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="UpdateIndexerOnSaveActionGroup" stepKey="resetIndexerBackToOriginalState"> <argument name="indexerName" value="catalogsearch_fulltext"/> </actionGroup> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -42,7 +42,7 @@ <actionGroup ref="UpdateIndexerByScheduleActionGroup" stepKey="updateAnIndexerBySchedule"> <argument name="indexerName" value="catalogsearch_fulltext"/> </actionGroup> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <!--Navigate to storefront and do a quick search for the product --> <comment userInput="Navigate to Storefront to check if quick search works" stepKey="commentCheckQuickSearch" /> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> diff --git a/app/code/Magento/Elasticsearch/Test/Mftf/Test/StorefrontCheckAdvancedSearchOnElasticSearchTest.xml b/app/code/Magento/Elasticsearch/Test/Mftf/Test/StorefrontCheckAdvancedSearchOnElasticSearchTest.xml new file mode 100644 index 0000000000000..7380ec085e0f3 --- /dev/null +++ b/app/code/Magento/Elasticsearch/Test/Mftf/Test/StorefrontCheckAdvancedSearchOnElasticSearchTest.xml @@ -0,0 +1,154 @@ +<?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="StorefrontCheckAdvancedSearchOnElasticSearchTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Storefront Search"/> + <title value="Check Advanced Search on ElasticSearch"/> + <description value="Check Advanced Search on ElasticSearch"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-31745"/> + <group value="SearchEngineElasticsearch"/> + <group value="configurableProduct"/> + <group value="catalog_search"/> + </annotations> + + <before> + <!--Delete all product if exists--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndexPage"/> + <actionGroup ref="DeleteProductsIfTheyExistActionGroup" stepKey="deleteAllProducts"/> + + <actionGroup ref="CreateApiConfigurableProductWithDescriptionActionGroup" stepKey="createConfigurableProduct"> + <argument name="productName" value="Product A"/> + </actionGroup> + <actionGroup ref="CreateApiConfigurableProductWithDescriptionActionGroup" stepKey="createConfigurableProductTwo"> + <argument name="productName" value="Product1234"/> + </actionGroup> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + <magentoCLI command="cache:flush" arguments="full_page" stepKey="flushFullPageCache"/> + </before> + + <after> + <!-- Delete configurable products data --> + <deleteData createDataKey="createConfigChildProduct1CreateConfigurableProduct" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2CreateConfigurableProduct" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductCreateConfigurableProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttributeCreateConfigurableProduct" stepKey="deleteConfigProductAttribute"/> + + <deleteData createDataKey="createConfigChildProduct1CreateConfigurableProductTwo" stepKey="deleteConfigChildProduct1ForSecondProduct"/> + <deleteData createDataKey="createConfigChildProduct2CreateConfigurableProductTwo" stepKey="deleteConfigChildProduct2ForSecondProduct"/> + <deleteData createDataKey="createConfigProductCreateConfigurableProductTwo" stepKey="deleteConfigProductTwo"/> + <deleteData createDataKey="createConfigProductAttributeCreateConfigurableProductTwo" stepKey="deleteConfigProductAttributeForSecondProduct"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <!-- Navigate to Frontend --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToStorefront"/> + + <!-- Click "Advanced Search" --> + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="openAdvancedSearch"/> + + <!-- Fill Configurable name in to field. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByName"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResult"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentOnCategoryPage"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToStoreViewAdvancedCatalogSearch"/> + <!-- Fill Configurable Two name in to field. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductTwoByName"> + <argument name="productName" value="$createConfigProductCreateConfigurableProductTwo.name$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="checkResultSearchConfigurableProductByName"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductTwoIsPresentOnCategoryPage"> + <argument name="productName" value="$createConfigProductCreateConfigurableProductTwo.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedCatalogSearchPage"/> + <!-- Fill Configurable partial name in to field. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByPartialName"> + <argument name="productName" value="Product"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="checkResultSearchConfigurableProductByPartialName"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductOneIsPresentAfterSearchByPartialName"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductTwoIsPresentAfterSearchByPartialName"> + <argument name="productName" value="$createConfigProductCreateConfigurableProductTwo.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedSearchForSearchProductByDescription"/> + <!-- Fill Configurable short description in to field. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByDescription"> + <argument name="description" value="$createConfigProductCreateConfigurableProduct.product[custom_attributes][0][value]$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResultAfterSearchByDescription"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentAfterSearchByDescription"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedSearchForSearchProductByShortDescription"/> + <!-- Fill Configurable short description in to field. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByShortDescription"> + <argument name="short_description" value="$createConfigProductCreateConfigurableProduct.product[custom_attributes][1][value]$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResultAfterSearchByShortDescription"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentAfterSearchByShortDescription"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedSearchForSearchProductsByPrice"/> + <!-- Fill Configurable price in to fields. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByPrice"> + <argument name="price_from" value="40"/> + <argument name="price_to" value="123"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResultAfterSearchByPrice"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentAfterSearchByPrice"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductTwoIsPresentAfterSearchByPrice"> + <argument name="productName" value="$createConfigProductCreateConfigurableProductTwo.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedCatalogSearchPageForSearchByDescriptionAndAttribute"/> + <!-- Fill Configurable description in to field and select attribute. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchWithCustomDropDownAttributeActionGroup" stepKey="searchConfigurableProductByDescriptionAndAttribute"> + <argument name="description" value="$createConfigProductCreateConfigurableProduct.product[custom_attributes][0][value]$"/> + <argument name="attributeCode" value="$createConfigProductAttributeCreateConfigurableProduct.attribute[attribute_code]$"/> + <argument name="optionName" value="$createConfigProductAttributeOption1CreateConfigurableProduct.option[store_labels][0][label]$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResultAfterSearchByDescriptionAndAttribute"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentAfterSearchByDescriptionAndAttribute"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + + <actionGroup ref="StorefrontOpenAdvancedSearchActionGroup" stepKey="goToAdvancedSearchForSearchProductByDescriptionAndShortDescription"/> + <!-- Fill Configurable description and short description in to fields. Click "Search" button and assert product present--> + <actionGroup ref="StorefrontFillFormAdvancedSearchActionGroup" stepKey="searchConfigurableProductByDescriptionAndShortDescription"> + <argument name="description" value="$createConfigProductCreateConfigurableProduct.product[custom_attributes][0][value]$"/> + <argument name="short_description" value="$createConfigProductCreateConfigurableProduct.product[custom_attributes][1][value]$"/> + </actionGroup> + <actionGroup ref="StorefrontCheckAdvancedSearchResultActionGroup" stepKey="storefrontCheckAdvancedSearchResultAfterSearchByDescriptionAndShortDescription"/> + <actionGroup ref="AssertStorefrontProductIsPresentOnCategoryPageActionGroup" stepKey="assertConfigurableProductIsPresentAfterSearchByDescriptionAndShortDescription"> + <argument name="productName" value="$createConfigProductCreateConfigurableProduct.name$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticSearchForChineseLocaleTest.xml b/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticSearchForChineseLocaleTest.xml index fd18a0f4e1e5e..71e0401a1c30a 100644 --- a/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticSearchForChineseLocaleTest.xml +++ b/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticSearchForChineseLocaleTest.xml @@ -38,7 +38,7 @@ <magentoCLI command="config:set {{SetDefaultSearchEngineConfig.path}} {{SetDefaultSearchEngineConfig.value}}" stepKey="resetSearchEnginePreviousState"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!-- Search for product by name --> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> diff --git a/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticsearch6SearchInvalidValueTest.xml b/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticsearch6SearchInvalidValueTest.xml index 050ce1263d10d..622b78fce01b9 100644 --- a/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticsearch6SearchInvalidValueTest.xml +++ b/app/code/Magento/Elasticsearch6/Test/Mftf/Test/StorefrontElasticsearch6SearchInvalidValueTest.xml @@ -50,7 +50,7 @@ <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetFiltersIfExist"/> <magentoCLI command="indexer:reindex catalogsearch_fulltext" stepKey="reindex"/> <magentoCLI command="cache:flush config" stepKey="flushCache"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new searchable product attribute--> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="goToProductAttributes"/> diff --git a/app/code/Magento/Email/Test/Mftf/ActionGroup/AdminUploadTransactionEmailsImageActionGroup.xml b/app/code/Magento/Email/Test/Mftf/ActionGroup/AdminUploadTransactionEmailsImageActionGroup.xml new file mode 100644 index 0000000000000..a34736a71163e --- /dev/null +++ b/app/code/Magento/Email/Test/Mftf/ActionGroup/AdminUploadTransactionEmailsImageActionGroup.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="AdminUploadTransactionEmailsImageActionGroup"> + <annotations> + <description>Upload logo image for email</description> + </annotations> + <arguments> + <argument name="image" type="string" defaultValue="{{MagentoLogo.file}}"/> + <argument name="width" type="string" defaultValue="200"/> + <argument name="height" type="string" defaultValue="100"/> + </arguments> + + <conditionalClick selector="{{AdminDesignConfigSection.transactionalEmailSectionHeader}}" dependentSelector="{{AdminDesignConfigSection.transactionalEmailSectionBody}}" visible="false" stepKey="openTransactionalEmailSection"/> + <waitForElementVisible selector="{{AdminDesignConfigSection.logoImageAlt}}" stepKey="waitVisibleUploadLogo"/> + <attachFile selector="{{AdminDesignConfigSection.logoUpload}}" userInput="{{image}}" stepKey="attachLogo"/> + <waitForElementVisible selector="{{AdminDesignConfigSection.logoPreview}}" stepKey="waitingForLogoToUpload"/> + <seeElement selector="{{AdminDesignConfigSection.logoPreview}}" stepKey="logoPreviewIsVisible"/> + <fillField selector="{{AdminDesignConfigSection.logoImageAlt}}" userInput="{{image}}" stepKey="fillFieldImageAlt"/> + <fillField selector="{{AdminDesignConfigSection.logoImageWidth}}" userInput="{{width}}" stepKey="fillFieldImageWidth"/> + <fillField selector="{{AdminDesignConfigSection.logoImageHeight}}" userInput="{{height}}" stepKey="fillFieldImageHeight"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml index ca73de1f88fcc..92f4b79b09be2 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="DeleteEmailTemplateActionGroup" stepKey="deleteTemplate"/> <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clearFilters"/> <!--Logout from Admin Area--> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="CreateCustomTemplateActionGroup" stepKey="createTemplate"/> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminMarketingEmailTemplatesNavigateMenuTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminMarketingEmailTemplatesNavigateMenuTest.xml index d512fc263ef2c..28e77ee399737 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminMarketingEmailTemplatesNavigateMenuTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminMarketingEmailTemplatesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToMarketingEmailTemplatesPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml index 9e1d9c5c3cdbb..89b07e4be44e9 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/TransactionalEmailsLogoUploadTest.xml @@ -11,33 +11,44 @@ <test name="TransactionalEmailsLogoUploadTest"> <annotations> <features value="Email"/> - <stories value="Email"/> - <title value="MC-13908: Uploading a Transactional Emails logo"/> + <stories value="Transactional Emails logo"/> + <title value="Uploading a Transactional Emails logo"/> <description value="Transactional Emails Logo should be able to be uploaded in the admin and previewed"/> <severity value="CRITICAL"/> - <testCaseId value="MC-13908"/> - <group value="LogoUpload"/> - <skip> - <issueId value="MC-18496"/> - </skip> + <testCaseId value="MC-27620"/> + <useCaseId value="MC-10932"/> + <group value="theme"/> + <group value="email"/> </annotations> - <!--Login to Admin Area--> <before> - <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> + <!--Login to Admin Area--> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> - <!--Logout from Admin Area--> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <!-- Clear filter on Design Config Page --> + <amOnPage url="{{DesignConfigPage.url}}" stepKey="navigateToDesignConfigPage" /> + <waitForPageLoad stepKey="waitForPageLoadToViewDesignConfigPage"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> + <!--Logout from Admin Area--> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Navigate to content->Design->Config page--> <amOnPage url="{{DesignConfigPage.url}}" stepKey="navigateToDesignConfigPage" /> - <waitForPageLoad stepKey="waitForPageloadToViewDesignConfigPage"/> - <click selector="{{AdminDesignConfigSection.scopeRow('3')}}" stepKey="editStoreView"/> + <waitForPageLoad stepKey="waitForPageLoadToViewDesignConfigPage"/> + <actionGroup ref="AdminGridFilterSearchResultsBySelectActionGroup" stepKey="filterThemeDesignConfiguration"> + <argument name="attributeSelector" value="store_id"/> + <argument name="attributeValue" value="{{_defaultStore.name}}"/> + </actionGroup> + <click selector="{{AdminDesignConfigSection.scopeRow('1')}}" stepKey="editStoreView"/> <waitForPageLoad stepKey="waitForPageLoadToOpenStoreViewEditPage"/> - <!--Click Upload logo in Transactional Emails and upload the image and preview it--> - <click selector="{{AdminDesignConfigSection.logoWrapperOpen}}" stepKey="openTab" /> - <attachFile selector="{{AdminDesignConfigSection.logoUpload}}" userInput="{{MagentoLogo.file}}" stepKey="attachLogo"/> - <wait time="5" stepKey="waitingForLogoToUpload" /> - <seeElement selector="{{AdminDesignConfigSection.logoPreview}}" stepKey="LogoPreviewIsVisible"/> + <!-- Upload Image --> + <actionGroup ref="AdminUploadTransactionEmailsImageActionGroup" stepKey="uploadImage"> + <argument name="width" value="200"/> + <argument name="height" value="100"/> + </actionGroup> + <!--Save Design Configuration --> + <actionGroup ref="ClickSaveButtonActionGroup" stepKey="saveDesignConfiguration"> + <argument name="message" value="You saved the configuration."/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyAutoGenerateKeyTest.xml b/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyAutoGenerateKeyTest.xml index ded57f4aad019..04430661a62a4 100644 --- a/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyAutoGenerateKeyTest.xml +++ b/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyAutoGenerateKeyTest.xml @@ -25,7 +25,7 @@ <after> <!--Logout from Admin Area--> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="AdminEncryptionKeyNavigateToChangePageActionGroup" stepKey="navigateToPage"/> diff --git a/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyManualGenerateKeyTest.xml b/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyManualGenerateKeyTest.xml index f3a9849969263..0674fd12ebead 100644 --- a/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyManualGenerateKeyTest.xml +++ b/app/code/Magento/EncryptionKey/Test/Mftf/Test/AdminEncryptionKeyManualGenerateKeyTest.xml @@ -25,7 +25,7 @@ <after> <!--Logout from Admin Area--> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="AdminEncryptionKeyNavigateToChangePageActionGroup" stepKey="navigateToPage"/> diff --git a/app/code/Magento/Fedex/Test/Mftf/Test/AdminCreatingShippingLabelTest.xml b/app/code/Magento/Fedex/Test/Mftf/Test/AdminCreatingShippingLabelTest.xml index 016c609ae7762..c0b602e772b54 100644 --- a/app/code/Magento/Fedex/Test/Mftf/Test/AdminCreatingShippingLabelTest.xml +++ b/app/code/Magento/Fedex/Test/Mftf/Test/AdminCreatingShippingLabelTest.xml @@ -75,7 +75,7 @@ <!--Delete created data--> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Add country of manufacture to product--> <amOnPage url="{{AdminProductEditPage.url($$createProduct.id$$)}}" stepKey="amOnEditPage"/> diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/MergeQuoteItemsTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/MergeQuoteItemsTest.php new file mode 100644 index 0000000000000..873a31aba46df --- /dev/null +++ b/app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/MergeQuoteItemsTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\GiftMessage\Test\Unit\Model\Plugin; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\GiftMessage\Model\Plugin\MergeQuoteItems; +use Magento\Quote\Model\Quote\Item; +use Magento\Quote\Model\Quote\Item\Processor; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\GiftMessage\Model\Plugin\MergeQuoteItems + */ +class MergeQuoteItemsTest extends TestCase +{ + private const STUB_GIFT_MESSAGE = 'message'; + + /** + * @var MergeQuoteItems + */ + private $plugin; + + /** + * @var Processor|MockObject + */ + private $processorMock; + + /** + * @var Item|MockObject + */ + private $resultMock; + + /** + * @var Item|MockObject + */ + private $sourceMock; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->plugin = (new ObjectManagerHelper($this))->getObject(MergeQuoteItems::class); + $this->processorMock = $this->createMock(Processor::class); + $this->resultMock = $this->createPartialMock(Item::class, ['setGiftMessageId']); + $this->sourceMock = $this->createPartialMock(Item::class, ['getGiftMessageId']); + } + + /** + * Test case when a source item has a Gift message. + */ + public function testAfterMergeExpectsSetGiftMessageIdCalled(): void + { + $this->sourceMock->expects($this->once()) + ->method('getGiftMessageId') + ->willReturn(self::STUB_GIFT_MESSAGE); + $this->resultMock->expects($this->once()) + ->method('setGiftMessageId') + ->with(self::STUB_GIFT_MESSAGE); + + $this->assertSame( + $this->resultMock, + $this->plugin->afterMerge($this->processorMock, $this->resultMock, $this->sourceMock) + ); + } + + /** + * Test case when a source item doesn't have a Gift message. + */ + public function testAfterMergeWithoutGiftMessageId(): void + { + $this->sourceMock->expects($this->once())->method('getGiftMessageId')->willReturn(null); + $this->resultMock->expects($this->never())->method('setGiftMessageId'); + + $this->assertSame( + $this->resultMock, + $this->plugin->afterMerge($this->processorMock, $this->resultMock, $this->sourceMock) + ); + } +} diff --git a/app/code/Magento/GoogleAdwords/Test/Mftf/Test/AdminValidateConversionIdConfigTest.xml b/app/code/Magento/GoogleAdwords/Test/Mftf/Test/AdminValidateConversionIdConfigTest.xml index 7c0214a8654c8..bc1983344ce88 100644 --- a/app/code/Magento/GoogleAdwords/Test/Mftf/Test/AdminValidateConversionIdConfigTest.xml +++ b/app/code/Magento/GoogleAdwords/Test/Mftf/Test/AdminValidateConversionIdConfigTest.xml @@ -19,7 +19,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateToGoogleAdwordsConfigurationActionGroup" stepKey="goToConfigPage"/> <actionGroup ref="AdminExpandConfigSectionActionGroup" stepKey="expandingGoogleAdwordsSection"> diff --git a/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php b/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php new file mode 100644 index 0000000000000..6df890b3e94dc --- /dev/null +++ b/app/code/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/Grouped.php @@ -0,0 +1,40 @@ +<?php +/** + * Order Email items grouped renderer + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo; + +use Magento\Sales\Block\Order\Email\Items\DefaultItems; + +/** + * Class renders grouped product(s) in the CreditMemo email + * + * @api + */ +class Grouped extends DefaultItems +{ + /** + * Prepare item html + * + * This method uses renderer for real product type + * + * @return string + */ + protected function _toHtml() + { + if ($this->getItem()->getOrderItem()) { + $item = $this->getItem()->getOrderItem(); + } else { + $item = $this->getItem(); + } + if ($productType = $item->getRealProductType()) { + $renderer = $this->getRenderedBlock()->getItemRenderer($productType); + $renderer->setItem($this->getItem()); + return $renderer->toHtml(); + } + return parent::_toHtml(); + } +} diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminAssociateGroupedProductToWebsitesTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminAssociateGroupedProductToWebsitesTest.xml index 41096c416d05e..d23013a6157c9 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminAssociateGroupedProductToWebsitesTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminAssociateGroupedProductToWebsitesTest.xml @@ -72,7 +72,7 @@ <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridFilter"/> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open product page and assign grouped project to second website --> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminCreateAndEditGroupedProductSettingsTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminCreateAndEditGroupedProductSettingsTest.xml index e3b76dafdd100..c6228e674aa34 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminCreateAndEditGroupedProductSettingsTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminCreateAndEditGroupedProductSettingsTest.xml @@ -43,7 +43,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create new grouped product --> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml index f7b9357f1b34a..ebcdc0623cd75 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminDeleteGroupedProductTest.xml @@ -31,7 +31,7 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteGroupedProductFilteredBySkuAndName"> <argument name="product" value="$$createGroupedProduct$$"/> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedProductsListTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedProductsListTest.xml index d80e68e37c44c..151a987ea89cc 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedProductsListTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedProductsListTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> <deleteData createDataKey="category1" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create product --> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml index fdffd286d632f..a0698224b780c 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml @@ -34,6 +34,8 @@ <argument name="product" value="GroupedProduct"/> </actionGroup> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <!--See related product in storefront--> <amOnPage url="{{GroupedProduct.sku}}.html" stepKey="goToStorefront"/> </test> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminSortingAssociatedProductsTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminSortingAssociatedProductsTest.xml index bac294d59ce51..dd4619c5c2ce1 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminSortingAssociatedProductsTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminSortingAssociatedProductsTest.xml @@ -123,7 +123,7 @@ <deleteData createDataKey="product22" stepKey="deleteProduct22"/> <deleteData createDataKey="product23" stepKey="deleteProduct23"/> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create grouped Product--> diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml index 77875ac70427c..2e64b3047cbbb 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/sales_email_order_creditmemo_renderers.xml @@ -8,7 +8,7 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Creditmemo Items List" design_abstraction="custom"> <body> <referenceBlock name="sales.email.order.creditmemo.renderers"> - <block class="Magento\GroupedProduct\Block\Order\Email\Items\Order\Grouped" name="sales.email.order.creditmemo.renderers.grouped" as="grouped" template="Magento_Sales::email/items/creditmemo/default.phtml"/> + <block class="Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo\Grouped" name="sales.email.order.creditmemo.renderers.grouped" as="grouped" template="Magento_Sales::email/items/creditmemo/default.phtml"/> </referenceBlock> </body> </page> diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php index 9e7cd6a29dc9a..d580af6f92baf 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config.php +++ b/app/code/Magento/ImportExport/Model/Export/Config.php @@ -15,10 +15,11 @@ class Config extends \Magento\Framework\Config\Data implements \Magento\ImportEx /** * Constructor * - * @param Config\Reader $reader + * @param \Magento\ImportExport\Model\Export\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string|null $cacheId - * @param SerializerInterface|null $serializer + * @param string $cacheId + * @param SerializerInterface $serializer + * phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod */ public function __construct( \Magento\ImportExport\Model\Export\Config\Reader $reader, @@ -48,7 +49,7 @@ public function getEntities() public function getEntityTypes($entity) { $entities = $this->getEntities(); - return isset($entities[$entity]) ? $entities[$entity]['types'] : []; + return $entities[$entity]['types'] ?? []; } /** diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEav.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEav.php index 82c4478874844..7cd700daf05f9 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEav.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEav.php @@ -10,8 +10,8 @@ /** * Import EAV entity abstract model * + * phpcs:disable Magento2.Classes.AbstractApi * @api - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ @@ -19,6 +19,8 @@ abstract class AbstractEav extends \Magento\ImportExport\Model\Import\AbstractEn { /** * Attribute collection name + * + * Name of collection class */ const ATTRIBUTE_COLLECTION_NAME = \Magento\Framework\Data\Collection::class; @@ -129,7 +131,7 @@ public function __construct( public function getWebsiteId($websiteCode) { if (isset($this->_websiteCodeToId[$websiteCode])) { - return $this->_websiteCodeToId[$websiteCode]; + return (int) $this->_websiteCodeToId[$websiteCode]; } return false; @@ -232,6 +234,7 @@ public function getAttributeOptions( } } } + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Exception $e) { // ignore exceptions connected with source models } diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckDoubleImportOfProductsTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckDoubleImportOfProductsTest.xml deleted file mode 100644 index e710d9add4c21..0000000000000 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckDoubleImportOfProductsTest.xml +++ /dev/null @@ -1,73 +0,0 @@ -<?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="AdminCheckDoubleImportOfProductsTest"> - <annotations> - <description value="Checking double Import of products CSV file"/> - <stories value="Import Products"/> - <features value="Import/Export"/> - <title value="Admin check double import of products test"/> - <severity value="CRITICAL"/> - <testCaseId value="MC-6311"/> - <group value="importExport"/> - </annotations> - <before> - <!-- Login as admin --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - - <!-- Create additional store views --> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createFirstStoreView"> - <argument name="customStore" value="secondStoreView"/> - </actionGroup> - <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createSecondStoreView"> - <argument name="customStore" value="thirdStoreView"/> - </actionGroup> - </before> - <after> - <!-- Delete all imported products --> - <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/> - <actionGroup ref="AdminDataGridSelectPerPageActionGroup" stepKey="selectNumberOfProductsPerPage"> - <argument name="perPage" value="100"/> - </actionGroup> - <actionGroup ref="DeleteProductsIfTheyExistActionGroup" stepKey="deleteAllProducts"/> - - <!-- Delete additional store views --> - <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteFirstStoreView"> - <argument name="customStore" value="secondStoreView"/> - </actionGroup> - <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteSecondStoreView"> - <argument name="customStore" value="thirdStoreView"/> - </actionGroup> - - <!-- Delete category --> - <actionGroup ref="DeleteCategoryActionGroup" stepKey="deleteCategory"> - <argument name="categoryEntity" value="Gear"/> - </actionGroup> - - <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> - </after> - - <!-- Import products with add/update behavior --> - <actionGroup ref="AdminImportProductsActionGroup" stepKey="adminImportProductsFirstTime"> - <argument name="behavior" value="Add/Update"/> - <argument name="importFile" value="prepared-for-sample-data.csv"/> - <argument name="importNoticeMessage" value="Created: 100, Updated: 3, Deleted: 0"/> - </actionGroup> - - <!-- Import products with add/update behavior again --> - <actionGroup ref="AdminImportProductsActionGroup" stepKey="adminImportProductsSecondTime"> - <argument name="behavior" value="Add/Update"/> - <argument name="importFile" value="prepared-for-sample-data.csv"/> - <argument name="importNoticeMessage" value="Created: 0, Updated: 300, Deleted: 0"/> - </actionGroup> - </test> -</tests> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml index 6a2f6ca60acf4..9ccdb313b88e6 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml @@ -41,7 +41,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <!--Delete attribute--> <deleteData createDataKey="productAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Create product--> <actionGroup ref="GoToSpecifiedCreateProductPageActionGroup" stepKey="openProductFillForm"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPageNavigateMenuTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPageNavigateMenuTest.xml index e8fb12ca521c2..eba744e551037 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPageNavigateMenuTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPageNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToExportPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPagerGridTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPagerGridTest.xml index b203a4d11a2d2..b52d8ec729fc0 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPagerGridTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminExportPagerGridTest.xml @@ -21,7 +21,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateToExportPageActionGroup" stepKey="navigateToExportPage"/> <actionGroup ref="AdminAssertVisiblePagerActionGroup" stepKey="seeGridPager"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImagesFileDirectoryCorrectExplanationTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImagesFileDirectoryCorrectExplanationTest.xml index 989c405324f06..92f93736f237a 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImagesFileDirectoryCorrectExplanationTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImagesFileDirectoryCorrectExplanationTest.xml @@ -21,7 +21,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{AdminImportIndexPage.url}}" stepKey="goToImportIndexPage"/> <waitForPageLoad stepKey="adminImportMainSectionLoad"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportCSVWithSpecialCharactersTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportCSVWithSpecialCharactersTest.xml index 38c1a09dc534c..91d1209f1f1b8 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportCSVWithSpecialCharactersTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportCSVWithSpecialCharactersTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="AdminCheckDataForImportProductActionGroup" stepKey="adminImportProducts"> <argument name="behavior" value="Add/Update"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithAddUpdateBehaviorTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithAddUpdateBehaviorTest.xml index 796732d572290..3eebb9def9c7a 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithAddUpdateBehaviorTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithAddUpdateBehaviorTest.xml @@ -65,7 +65,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!-- Import products with add/update behavior --> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml index 7ec48a3a7e8fd..9934ac2e0c8c2 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithDeleteBehaviorTest.xml @@ -38,7 +38,7 @@ </before> <after> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{AdminImportIndexPage.url}}" stepKey="goToImportIndexPage"/> <selectOption selector="{{AdminImportMainSection.entityType}}" userInput="Products" stepKey="selectProductsOption"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithErrorEntriesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithErrorEntriesTest.xml index e3065f005218b..1d3a45b79dc74 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithErrorEntriesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportProductsWithErrorEntriesTest.xml @@ -27,7 +27,7 @@ <!--Delete all imported products--> <actionGroup ref="DeleteProductsIfTheyExistActionGroup" stepKey="deleteAllProducts"/> <!--Logout from Admin page--> - <actionGroup ref="logout" stepKey="logoutFromAdminPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdminPage"/> </after> <!--Import products with "Skip error entries"--> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductImportCSVFileCorrectDifferentFilesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductImportCSVFileCorrectDifferentFilesTest.xml index 56c1c43bc28d2..593282b9bb867 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductImportCSVFileCorrectDifferentFilesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductImportCSVFileCorrectDifferentFilesTest.xml @@ -25,7 +25,7 @@ </before> <after> <!--Logout from Admin--> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Check data products with add/update behavior--> <actionGroup ref="AdminCheckDataForImportProductActionGroup" stepKey="adminImportProducts"> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductVisibilityDifferentStoreViewsAfterImportTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductVisibilityDifferentStoreViewsAfterImportTest.xml index f0d721075fdfd..de3b52c3c3a98 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductVisibilityDifferentStoreViewsAfterImportTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminProductVisibilityDifferentStoreViewsAfterImportTest.xml @@ -46,7 +46,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteChineseStoreView"> <argument name="customStore" value="storeViewChinese"/> </actionGroup> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Import products from file--> <actionGroup ref="AdminImportProductsActionGroup" stepKey="importProducts"> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminSystemImportNavigateMenuTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminSystemImportNavigateMenuTest.xml index 9913933d857a8..249f3b28f7a56 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminSystemImportNavigateMenuTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminSystemImportNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToImportPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminURLKeyWorksWhenUpdatingProductThroughImportingCSVTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminURLKeyWorksWhenUpdatingProductThroughImportingCSVTest.xml index 8d56d9d8dad9d..4d4e87f9387cc 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminURLKeyWorksWhenUpdatingProductThroughImportingCSVTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminURLKeyWorksWhenUpdatingProductThroughImportingCSVTest.xml @@ -31,7 +31,7 @@ <!--Delete created data--> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Import product from CSV file--> <actionGroup ref="AdminImportProductsActionGroup" stepKey="importProduct"> diff --git a/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml new file mode 100644 index 0000000000000..9dc7547db40d6 --- /dev/null +++ b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml @@ -0,0 +1,18 @@ +<?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="CliRunReindexUsingCronJobsActionGroup"> + <annotations> + <description>Run cron 'index' group which reindex all invalidated indices.</description> + </annotations> + + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="firstRunToScheduleJobs"/> + <magentoCLI command="cron:run" arguments="--group='index'" stepKey="secondRunToExecuteJobs"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Indexer/Test/Mftf/ActionGroup/IndexerActionGroup.xml b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/IndexerActionGroup.xml new file mode 100644 index 0000000000000..82dbb416122d8 --- /dev/null +++ b/app/code/Magento/Indexer/Test/Mftf/ActionGroup/IndexerActionGroup.xml @@ -0,0 +1,52 @@ +<?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="updateIndexerBySchedule"> + <annotations> + <description>Goes to the Index Management page. Checks the provided Indexer Name. Selects 'Update by Schedule'. Clicks on Submit.</description> + </annotations> + <arguments> + <argument name="indexerName" type="string"/> + </arguments> + + <amOnPage url="{{_ENV.MAGENTO_BACKEND_NAME}}/indexer/indexer/list/" stepKey="amOnIndexManagementPage"/> + <waitForPageLoad stepKey="waitForIndexManagementPageToLoad"/> + <click selector="{{AdminIndexManagementSection.indexerCheckbox(indexerName)}}" stepKey="selectIndexer1"/> + <selectOption selector="{{AdminIndexManagementSection.massActionSelect}}" userInput="change_mode_changelog" stepKey="selectUpdateBySchedule"/> + <click selector="{{AdminIndexManagementSection.massActionSubmit}}" stepKey="submitIndexerForm"/> + <!-- No re-indexing is done as part of this actionGroup since the test required no re-indexing --> + <waitForPageLoad stepKey="waitForSave"/> + </actionGroup> + + <actionGroup name="updateIndexerOnSave"> + <annotations> + <description>Goes to the Index Management page. Checks the provided Indexer Name. Selects 'Update on Save'. Clicks on Submit.</description> + </annotations> + <arguments> + <argument name="indexerName" type="string"/> + </arguments> + + <amOnPage url="{{_ENV.MAGENTO_BACKEND_NAME}}/indexer/indexer/list/" stepKey="amOnIndexManagementPage2"/> + <waitForPageLoad stepKey="waitForIndexManagementPageToLoad2"/> + <click selector="{{AdminIndexManagementSection.indexerCheckbox(indexerName)}}" stepKey="selectIndexer2"/> + <selectOption selector="{{AdminIndexManagementSection.massActionSelect}}" userInput="change_mode_onthefly" stepKey="selectUpdateOnSave"/> + <click selector="{{AdminIndexManagementSection.massActionSubmit}}" stepKey="submitIndexerForm2"/> + <!-- No re-indexing is done as part of this actionGroup since the test required no re-indexing --> + <waitForPageLoad stepKey="waitForSave2"/> + </actionGroup> + <actionGroup name="AdminReindexAndFlushCache"> + <annotations> + <description>Run reindex and flush cache.</description> + </annotations> + + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <magentoCLI command="cache:flush" stepKey="flushCache"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementNavigateMenuTest.xml b/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementNavigateMenuTest.xml index 140c93f7f2b48..cbe5161e40ee8 100644 --- a/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementNavigateMenuTest.xml +++ b/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToIndexManagementPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> diff --git a/app/code/Magento/Integration/Test/Mftf/Test/AdminCreateIntegrationEntityWithDuplicatedNameTest.xml b/app/code/Magento/Integration/Test/Mftf/Test/AdminCreateIntegrationEntityWithDuplicatedNameTest.xml index b23436d474ed8..60598fdd27612 100644 --- a/app/code/Magento/Integration/Test/Mftf/Test/AdminCreateIntegrationEntityWithDuplicatedNameTest.xml +++ b/app/code/Magento/Integration/Test/Mftf/Test/AdminCreateIntegrationEntityWithDuplicatedNameTest.xml @@ -23,9 +23,9 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToIntegrationsPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> <argument name="submenuUiId" value="{{AdminMenuSystemExtensionsIntegrations.dataUiId}}"/> diff --git a/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml b/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml index 966be94d9e404..d1850fdc989fb 100644 --- a/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml +++ b/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml @@ -38,7 +38,7 @@ <actionGroup ref="AdminSubmitNewIntegrationFormActionGroup" stepKey="submitTheForm"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- TEST BODY --> diff --git a/app/code/Magento/Integration/Test/Mftf/Test/AdminSystemIntegrationsNavigateMenuTest.xml b/app/code/Magento/Integration/Test/Mftf/Test/AdminSystemIntegrationsNavigateMenuTest.xml index 3bd149d222c0e..483afc62c9808 100644 --- a/app/code/Magento/Integration/Test/Mftf/Test/AdminSystemIntegrationsNavigateMenuTest.xml +++ b/app/code/Magento/Integration/Test/Mftf/Test/AdminSystemIntegrationsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToIntegrationsPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml index fd8763891af93..80280178e4593 100644 --- a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml +++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/AdminSpecifyLayerNavigationConfigurationTest.xml @@ -20,11 +20,11 @@ </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Configure Layered Navigation in Stores -> Configuration -> Catalog -> Layered Navigation --> diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml index d2b462d0467a2..76a9cc8f920a1 100644 --- a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml +++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml @@ -35,7 +35,7 @@ <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> <resizeWindow width="1280" height="1024" stepKey="resizeWindowToDesktop"/> </after> <!-- Go to default attribute set edit page and add the product attribute to the set --> diff --git a/app/code/Magento/LayeredNavigation/Test/Unit/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserverTest.php b/app/code/Magento/LayeredNavigation/Test/Unit/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserverTest.php new file mode 100644 index 0000000000000..1541bee97efb3 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/Test/Unit/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserverTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\LayeredNavigation\Test\Unit\Observer\Edit\Tab\Front; + +use Magento\Config\Model\Config\Source\Yesno; +use Magento\Framework\Data\Form; +use Magento\Framework\Data\Form\Element\Fieldset; +use Magento\Framework\Event\Observer; +use Magento\Framework\Module\Manager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\LayeredNavigation\Observer\Edit\Tab\Front\ProductAttributeFormBuildFrontTabObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\LayeredNavigation\Observer\Edit\Tab\Front\ProductAttributeFormBuildFrontTabObserver + */ +class ProductAttributeFormBuildFrontTabObserverTest extends TestCase +{ + /** + * @var MockObject|Observer + */ + private $eventObserverMock; + + /** + * @var MockObject|Yesno + */ + private $optionListLock; + + /** + * @var MockObject|Manager + */ + private $moduleManagerMock; + + /** + * @var ProductAttributeFormBuildFrontTabObserver + */ + private $observer; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->optionListLock = $this->createMock(Yesno::class); + $this->moduleManagerMock = $this->createMock(Manager::class); + $this->eventObserverMock = $this->getMockBuilder(Observer::class) + ->disableOriginalConstructor() + ->setMethods(['getForm']) + ->getMock(); + + $objectManager = new ObjectManager($this); + $this->observer = $objectManager->getObject( + ProductAttributeFormBuildFrontTabObserver::class, + [ + 'optionList' => $this->optionListLock, + 'moduleManager' => $this->moduleManagerMock, + ] + ); + } + + /** + * Test case when module output is disabled + */ + public function testExecuteWhenOutputDisabled(): void + { + $this->moduleManagerMock->expects($this->once()) + ->method('isOutputEnabled') + ->with('Magento_LayeredNavigation') + ->willReturn(false); + + $this->eventObserverMock->expects($this->never())->method('getForm'); + + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when module output is enabled + */ + public function testExecuteWhenOutputEnabled(): void + { + $this->moduleManagerMock->expects($this->once()) + ->method('isOutputEnabled') + ->with('Magento_LayeredNavigation') + ->willReturn(true); + + $fieldsetMock = $this->createMock(Fieldset::class); + $fieldsetMock->expects($this->exactly(3))->method('addField'); + $formMock = $this->createMock(Form::class); + $formMock->expects($this->once()) + ->method('getElement') + ->with('front_fieldset') + ->willReturn($fieldsetMock); + + $this->eventObserverMock->expects($this->once()) + ->method('getForm') + ->willReturn($formMock); + + $this->observer->execute($this->eventObserverMock); + } +} diff --git a/app/code/Magento/MediaGallery/Test/Unit/Plugin/Product/Gallery/ProcessorTest.php b/app/code/Magento/MediaGallery/Test/Unit/Plugin/Product/Gallery/ProcessorTest.php new file mode 100644 index 0000000000000..94c3aaf5c2f19 --- /dev/null +++ b/app/code/Magento/MediaGallery/Test/Unit/Plugin/Product/Gallery/ProcessorTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\MediaGallery\Test\Unit\Plugin\Product\Gallery; + +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Gallery\Processor as ProcessorSubject; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\MediaGallery\Plugin\Product\Gallery\Processor; +use Magento\MediaGalleryApi\Model\Asset\Command\DeleteByPathInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Unit test for \Magento\MediaGallery\Plugin\Product\Gallery\Processor + */ +class ProcessorTest extends TestCase +{ + private const STUB_FILE_NAME = 'file'; + + /** + * @var DeleteByPathInterface|MockObject + */ + private $deleteMediaAssetByPathMock; + + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var ProcessorSubject|MockObject + */ + private $processorSubjectMock; + + /** + * @var Product|MockObject + */ + private $productMock; + + /** + * @var Processor + */ + private $plugin; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->processorSubjectMock = $this->createMock(ProcessorSubject::class); + $this->productMock = $this->createMock(Product::class); + + $this->deleteMediaAssetByPathMock = $this->getMockBuilder(DeleteByPathInterface::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['critical']) + ->getMockForAbstractClass(); + + $this->plugin = (new ObjectManagerHelper($this))->getObject( + Processor::class, + [ + 'deleteMediaAssetByPath' => $this->deleteMediaAssetByPathMock, + 'logger' => $this->loggerMock + ] + ); + } + + /** + * Successful test case. + */ + public function testAfterRemoveImageExpectsExecuteCalled() + { + $this->deleteMediaAssetByPathMock->expects($this->once()) + ->method('execute') + ->with(self::STUB_FILE_NAME); + $this->loggerMock->expects($this->never())->method('critical'); + + $actualResult = $this->plugin->afterRemoveImage( + $this->processorSubjectMock, + $this->processorSubjectMock, + $this->productMock, + self::STUB_FILE_NAME + ); + $this->assertSame($this->processorSubjectMock, $actualResult); + } + + /** + * Test case when passed File argument is not a string. + */ + public function testAfterRemoveImageWithIncorrectFile() + { + $this->deleteMediaAssetByPathMock->expects($this->never())->method('execute'); + $this->loggerMock->expects($this->never())->method('critical'); + + $actualResult = $this->plugin->afterRemoveImage( + $this->processorSubjectMock, + $this->processorSubjectMock, + $this->productMock, + ['non-string-argument' => self::STUB_FILE_NAME] + ); + $this->assertSame($this->processorSubjectMock, $actualResult); + } + + /** + * Test case when an Exception is thrown. + */ + public function testAfterRemoveImageExpectsExecuteWillThrowException() + { + $this->deleteMediaAssetByPathMock->expects($this->once()) + ->method('execute') + ->with(self::STUB_FILE_NAME) + ->willThrowException(new \Exception('Some Exception')); + $this->loggerMock->expects($this->once())->method('critical'); + + $actualResult = $this->plugin->afterRemoveImage( + $this->processorSubjectMock, + $this->processorSubjectMock, + $this->productMock, + self::STUB_FILE_NAME + ); + $this->assertSame($this->processorSubjectMock, $actualResult); + } +} diff --git a/app/code/Magento/MediaGallery/Test/Unit/Plugin/Wysiwyg/Images/StorageTest.php b/app/code/Magento/MediaGallery/Test/Unit/Plugin/Wysiwyg/Images/StorageTest.php new file mode 100644 index 0000000000000..0c653a9543b19 --- /dev/null +++ b/app/code/Magento/MediaGallery/Test/Unit/Plugin/Wysiwyg/Images/StorageTest.php @@ -0,0 +1,176 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\MediaGallery\Test\Unit\Plugin\Wysiwyg\Images; + +use Magento\Cms\Model\Wysiwyg\Images\Storage as StorageSubject; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\MediaGallery\Plugin\Wysiwyg\Images\Storage; +use Magento\MediaGalleryApi\Model\Asset\Command\DeleteByPathInterface; +use Magento\MediaGalleryApi\Model\Asset\Command\GetByPathInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Unit test for \Magento\MediaGallery\Plugin\Wysiwyg\Images\Storage + */ +class StorageTest extends TestCase +{ + const STUB_TARGET = '/stub/test.png'; + const STUB_RELATIVE_PATH = 'test.png'; + + /** + * @var Storage + */ + private $storage; + + /** + * @var GetByPathInterface|MockObject + */ + private $getMediaAssetByPathMock; + + /** + * @var DeleteByPathInterface|MockObject + */ + private $deleteMediaAssetByPathMock; + + /** + * @var Filesystem|MockObject + */ + private $filesystemMock; + + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var StorageSubject|MockObject + */ + private $storageSubjectMock; + + /** + * @var ReadInterface|MockObject + */ + private $readInterfaceMock; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->storageSubjectMock = $this->createMock(StorageSubject::class); + $this->filesystemMock = $this->createMock(Filesystem::class); + $this->getMediaAssetByPathMock = $this->createMock(GetByPathInterface::class); + $this->deleteMediaAssetByPathMock = $this->getMockBuilder(DeleteByPathInterface::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['critical']) + ->getMockForAbstractClass(); + $this->readInterfaceMock = $this->getMockBuilder(ReadInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getRelativePath']) + ->getMockForAbstractClass(); + + $this->storage = (new ObjectManagerHelper($this))->getObject( + Storage::class, + [ + 'getMediaAssetByPath' => $this->getMediaAssetByPathMock, + 'deleteMediaAssetByPath' => $this->deleteMediaAssetByPathMock, + 'filesystem' => $this->filesystemMock, + 'logger' => $this->loggerMock + ] + ); + } + + /** + * Test case when an exception is thrown during the method execution. + */ + public function testAfterDeleteFileExpectsDeleteMediaAssetExecuted() + { + $this->setupMocksToReturnCorrectRelativePath(); + $this->deleteMediaAssetByPathMock->expects($this->once())->method('execute'); + $this->loggerMock->expects($this->never())->method('critical'); + + $this->executeOriginalMethodWithCorrectTarget(); + } + + /** + * Test case when an exception is thrown during the method execution. + */ + public function testAfterDeleteFileWithException() + { + $this->setupMocksToReturnCorrectRelativePath(); + $this->deleteMediaAssetByPathMock->expects($this->once()) + ->method('execute') + ->willThrowException(new \Exception()); + $this->loggerMock->expects($this->once())->method('critical'); + + $this->executeOriginalMethodWithCorrectTarget(); + } + + /** + * Test case when the target is not a string. + */ + public function testAfterDeleteFileWhenTargetIsNotString() + { + $target = []; + $this->filesystemMock->expects($this->never())->method('getDirectoryRead'); + $this->deleteMediaAssetByPathMock->expects($this->never())->method('execute'); + $this->assertSame( + $this->storageSubjectMock, + $this->storage->afterDeleteFile($this->storageSubjectMock, $this->storageSubjectMock, $target) + ); + } + + /** + * Test case when there is no Relative Path which is need to be deleted. + */ + public function testAfterDeleteFileWhenRelativePathIsEmpty() + { + $this->readInterfaceMock->expects($this->once()) + ->method('getRelativePath') + ->willReturn(''); + $this->filesystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->willReturn($this->readInterfaceMock); + + $this->deleteMediaAssetByPathMock->expects($this->never())->method('execute'); + $this->executeOriginalMethodWithCorrectTarget(); + } + + /** + * Call the tested method + */ + private function executeOriginalMethodWithCorrectTarget() + { + $this->assertSame( + $this->storageSubjectMock, + $this->storage->afterDeleteFile($this->storageSubjectMock, $this->storageSubjectMock, self::STUB_TARGET) + ); + } + + /** + * Set mocks in order to return the relative path + */ + private function setupMocksToReturnCorrectRelativePath() + { + $this->readInterfaceMock->expects($this->once()) + ->method('getRelativePath') + ->willReturn(self::STUB_RELATIVE_PATH); + $this->filesystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->willReturn($this->readInterfaceMock); + } +} diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml index ccb724e8bf199..cfc841cbeb0f6 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml @@ -104,7 +104,10 @@ <!--Disable Minimum advertised Price--> <createData entity="MsrpDisableMAP" stepKey="disableMAP"/> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Set Manufacturer's Suggested Retail Price to products--> diff --git a/app/code/Magento/Msrp/view/base/web/js/msrp.js b/app/code/Magento/Msrp/view/base/web/js/msrp.js index 65af87d85de51..db407fbb22ce0 100644 --- a/app/code/Magento/Msrp/view/base/web/js/msrp.js +++ b/app/code/Magento/Msrp/view/base/web/js/msrp.js @@ -299,8 +299,9 @@ define([ * @param {Event} event * @param {mixed} priceIndex * @param {Object} prices + * @param {Object|undefined} $priceBox */ - onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices) { + onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices, $priceBox) { var defaultMsrp, defaultPrice, @@ -322,18 +323,20 @@ define([ finalPrice = prices[priceIndex].finalPrice.amount; if (msrpPrice === null || msrpPrice <= finalPrice) { - this.updateNonMsrpPrice(priceUtils.formatPrice(finalPrice)); + this.updateNonMsrpPrice(priceUtils.formatPrice(finalPrice), $priceBox); } else { this.updateMsrpPrice( priceUtils.formatPrice(finalPrice), priceUtils.formatPrice(msrpPrice), - false); + false, + $priceBox); } } else { this.updateMsrpPrice( priceUtils.formatPrice(defaultPrice), priceUtils.formatPrice(defaultMsrp), - true); + true, + $priceBox); } }, @@ -343,13 +346,14 @@ define([ * @param {String} finalPrice * @param {String} msrpPrice * @param {Boolean} useDefaultPrice + * @param {Object|undefined} $priceBox */ - updateMsrpPrice: function (finalPrice, msrpPrice, useDefaultPrice) { + updateMsrpPrice: function (finalPrice, msrpPrice, useDefaultPrice, $priceBox) { var options = this.tierOptions || this.options; - $(this.options.fallbackPriceContainer).hide(); - $(this.options.displayPriceContainer).show(); - $(this.options.mapInfoLinks).show(); + $(this.options.fallbackPriceContainer, $priceBox).hide(); + $(this.options.displayPriceContainer, $priceBox).show(); + $(this.options.mapInfoLinks, $priceBox).show(); if (useDefaultPrice || !this.wasOpened) { if (this.$popup) { @@ -357,14 +361,14 @@ define([ this.$popup.find(this.options.priceLabelId).html(options.realPrice); } - $(this.options.displayPriceElement).html(msrpPrice); + $(this.options.displayPriceElement, $priceBox).html(msrpPrice); this.wasOpened = true; } if (!useDefaultPrice) { this.$popup.find(this.options.msrpPriceElement).html(msrpPrice); this.$popup.find(this.options.priceElement).html(finalPrice); - $(this.options.displayPriceElement).html(msrpPrice); + $(this.options.displayPriceElement, $priceBox).html(msrpPrice); } }, @@ -372,12 +376,13 @@ define([ * Display non MAP price for irrelevant products * * @param {String} price + * @param {Object|undefined} $priceBox */ - updateNonMsrpPrice: function (price) { - $(this.options.fallbackPriceElement).html(price); - $(this.options.displayPriceContainer).hide(); - $(this.options.mapInfoLinks).hide(); - $(this.options.fallbackPriceContainer).show(); + updateNonMsrpPrice: function (price, $priceBox) { + $(this.options.fallbackPriceElement, $priceBox).html(price); + $(this.options.displayPriceContainer, $priceBox).hide(); + $(this.options.mapInfoLinks, $priceBox).hide(); + $(this.options.fallbackPriceContainer, $priceBox).show(); }, /** diff --git a/app/code/Magento/Multishipping/Model/Cart/CartTotalRepositoryPlugin.php b/app/code/Magento/Multishipping/Model/Cart/CartTotalRepositoryPlugin.php index 732bdee314f7c..bb225a5c46228 100644 --- a/app/code/Magento/Multishipping/Model/Cart/CartTotalRepositoryPlugin.php +++ b/app/code/Magento/Multishipping/Model/Cart/CartTotalRepositoryPlugin.php @@ -33,21 +33,21 @@ public function __construct( } /** - * Overwrite the CartTotalRepository quoteTotal and update the shipping price + * Check multishipping update shipping price after get cart total * - * @param CartTotalRepository $subject - * @param Totals $quoteTotals - * @param String $cartId - * @return Totals - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @param CartTotalRepository $subject + * @param Totals $quoteTotals + * @param int $cartId + * @return Totals + * @throws \Magento\Framework\Exception\NoSuchEntityException * @SuppressWarnings(PHPMD.UnusedLocalVariable) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterGet( CartTotalRepository $subject, Totals $quoteTotals, - String $cartId - ) { + $cartId + ) : Totals { $quote = $this->quoteRepository->getActive($cartId); if ($quote->getIsMultiShipping()) { $shippingMethod = $quote->getShippingAddress()->getShippingMethod(); diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithMultishipmentTest.xml index cfec857329b3d..a054649c5365c 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithMultishipmentTest.xml @@ -58,7 +58,7 @@ <deleteData stepKey="deleteProduct2" createDataKey="product2"/> <deleteData stepKey="deleteCustomer" createDataKey="customer"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShipping"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithSingleShipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithSingleShipmentTest.xml index dcf0770e5421e..de52d20542ce8 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithSingleShipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckingWithSingleShipmentTest.xml @@ -58,7 +58,7 @@ <deleteData stepKey="deleteProduct2" createDataKey="product2"/> <deleteData stepKey="deleteCustomer" createDataKey="customer"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShipping"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMinicartWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMinicartWithMultishipmentTest.xml index e826d8e03ffbc..90cc8b3952dde 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMinicartWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMinicartWithMultishipmentTest.xml @@ -44,7 +44,7 @@ <deleteData stepKey="deleteProduct2" createDataKey="product2"/> <deleteData stepKey="deleteCustomer" createDataKey="customer"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShipping"/> - <actionGroup ref="logout" stepKey="logoutAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdmin"/> </after> <amOnPage url="$$product1.name$$.html" stepKey="goToProduct1"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml index d8b6a35a4885c..8f27fa35bde02 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml @@ -50,7 +50,7 @@ <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <magentoCLI command="config:set {{DisableFreeShippingMethod.path}} {{DisableFreeShippingMethod.value}}" stepKey="disableFreeShipping"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearAllFilters"/> - <actionGroup ref="logout" stepKey="logoutAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdmin"/> </after> <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct1ToCart"> <argument name="product" value="$$product1$$"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontCheckoutWithMultipleAddressesTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontCheckoutWithMultipleAddressesTest.xml index dc786f9cbc5db..5890ab49b2587 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontCheckoutWithMultipleAddressesTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontCheckoutWithMultipleAddressesTest.xml @@ -36,7 +36,7 @@ </before> <after> <!-- Delete created data --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="firstProduct" stepKey="deleteFirstProduct"/> <deleteData createDataKey="secondProduct" stepKey="deleteSecondProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml index ef63d55ccfe35..9a3d622b2e264 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -46,7 +46,7 @@ <magentoCLI command="config:set {{DisableMultiShippingCheckoutMultiple.path}} {{DisableMultiShippingCheckoutMultiple.value}}" stepKey="withdrawShippingToMultipleAddresses"/> <magentoCLI command="config:set {{DisableFreeShippingMethod.path}} {{DisableFreeShippingMethod.value}}" stepKey="disableFreeShipping"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearAllOrdersGridFilters"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct1ToCart"> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontProcessMultishippingCheckoutWhenCartPageIsOpenedInAnotherTabTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontProcessMultishippingCheckoutWhenCartPageIsOpenedInAnotherTabTest.xml index f25ac203c3fa5..81b536746616e 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontProcessMultishippingCheckoutWhenCartPageIsOpenedInAnotherTabTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontProcessMultishippingCheckoutWhenCartPageIsOpenedInAnotherTabTest.xml @@ -36,7 +36,7 @@ </before> <after> <!-- Delete created data --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createFirstProduct" stepKey="deleteFirstProduct"/> <deleteData createDataKey="createSecondProduct" stepKey="deleteSecondProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Cart/CartTotalRepositoryPluginTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Cart/CartTotalRepositoryPluginTest.php index 73b0b9ef3ca7a..8362699efbd45 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Cart/CartTotalRepositoryPluginTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Cart/CartTotalRepositoryPluginTest.php @@ -6,76 +6,145 @@ namespace Magento\Multishipping\Test\Unit\Model\Cart; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Cart\CartTotalRepository; +use Magento\Quote\Model\Cart\Totals as QuoteTotals; +use Magento\Quote\Model\Quote\Address as QuoteAddress; +use Magento\Quote\Model\Quote\Address\Rate as QuoteAddressRate; +use Magento\Multishipping\Model\Cart\CartTotalRepositoryPlugin; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; + class CartTotalRepositoryPluginTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Multishipping\Model\Cart\CartTotalRepositoryPlugin + * Stub cart id + */ + private const STUB_CART_ID = 10; + + /** + * Stub shipping method + */ + private const STUB_SHIPPING_METHOD = 'flatrate_flatrate'; + + /** + * Stub shipping price + */ + private const STUB_SHIPPING_PRICE = '10.00'; + + /** + * @var CartTotalRepositoryPlugin */ private $modelRepository; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CartTotalRepository|MockObject + */ + private $quoteTotalRepositoryMock; + + /** + * @var CartRepositoryInterface|MockObject */ private $quoteRepositoryMock; - protected function setUp() - { - $this->quoteRepositoryMock = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class); - $this->modelRepository = new \Magento\Multishipping\Model\Cart\CartTotalRepositoryPlugin( - $this->quoteRepositoryMock - ); - } + /** + * @var QuoteTotals|MockObject + */ + private $quoteTotalsMock; /** - * Test quotTotal from cartRepository after get($cartId) function is called + * @var QuoteAddress|MockObject */ - public function testAfterGet() + private $shippingAddressMock; + + /** + * @var QuoteAddressRate|MockObject + */ + private $shippingRateMock; + + /** + * @var Store|MockObject + */ + private $storeMock; + + protected function setUp() { - $cartId = "10"; - $shippingMethod = 'flatrate_flatrate'; - $shippingPrice = '10.00'; - $quoteMock = $this->createPartialMock( - \Magento\Quote\Model\Cart\Totals::class, + $objectManager = new ObjectManager($this); + $this->quoteTotalsMock = $this->createPartialMock( + QuoteTotals::class, [ - 'getStore', - 'getShippingAddress', - 'getIsMultiShipping' + 'getStore', + 'getShippingAddress', + 'getIsMultiShipping' ] ); - $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with($cartId)->willReturn($quoteMock); - $quoteMock->expects($this->once())->method('getIsMultiShipping')->willReturn(true); - $shippingAddressMock = $this->createPartialMock( - \Magento\Quote\Model\Quote\Address::class, + $this->shippingAddressMock = $this->createPartialMock( + QuoteAddress::class, [ - 'getShippingMethod', - 'getShippingRateByCode', - 'getShippingAmount' + 'getShippingMethod', + 'getShippingRateByCode', + 'getShippingAmount' ] ); - $quoteMock->expects($this->any())->method('getShippingAddress')->willReturn($shippingAddressMock); - - $shippingAddressMock->expects($this->once())->method('getShippingMethod')->willReturn($shippingMethod); - $shippingAddressMock->expects($this->any())->method('getShippingAmount')->willReturn($shippingPrice); - $shippingRateMock = $this->createPartialMock( - \Magento\Quote\Model\Quote\Address\Rate::class, + $this->shippingRateMock = $this->createPartialMock( + QuoteAddressRate::class, [ - 'getPrice' + 'getPrice' ] ); - $shippingAddressMock->expects($this->once())->method('getShippingRateByCode')->willReturn($shippingRateMock); - - $shippingRateMock->expects($this->once())->method('getPrice')->willReturn($shippingPrice); - - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $this->storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->getMock(); - $quoteMock->expects($this->any())->method('getStore')->willReturn($storeMock); - $storeMock->expects($this->any())->method('getBaseCurrency')->willReturnSelf(); + $this->quoteRepositoryMock = $this->createMock(CartRepositoryInterface::class); + $this->quoteTotalRepositoryMock = $this->createMock(CartTotalRepository::class); + $this->modelRepository = $objectManager->getObject(CartTotalRepositoryPlugin::class, [ + 'quoteRepository' => $this->quoteRepositoryMock + ]); + } + + /** + * Test quoteTotal from cartRepository after get($cartId) function is called + */ + public function testAfterGetQuoteTotalAddedShippingPrice() + { + $this->quoteRepositoryMock->expects($this->once()) + ->method('getActive') + ->with(self::STUB_CART_ID) + ->willReturn($this->quoteTotalsMock); + $this->quoteTotalsMock->expects($this->once()) + ->method('getIsMultiShipping') + ->willReturn(true); + $this->quoteTotalsMock->expects($this->any()) + ->method('getShippingAddress') + ->willReturn($this->shippingAddressMock); + + $this->shippingAddressMock->expects($this->once()) + ->method('getShippingMethod') + ->willReturn(self::STUB_SHIPPING_METHOD); + $this->shippingAddressMock->expects($this->any()) + ->method('getShippingAmount') + ->willReturn(self::STUB_SHIPPING_PRICE); + + $this->shippingAddressMock->expects($this->once()) + ->method('getShippingRateByCode') + ->willReturn($this->shippingRateMock); + + $this->shippingRateMock->expects($this->once()) + ->method('getPrice') + ->willReturn(self::STUB_SHIPPING_PRICE); + + $this->quoteTotalsMock->expects($this->any()) + ->method('getStore') + ->willReturn($this->storeMock); + $this->storeMock->expects($this->any()) + ->method('getBaseCurrency') + ->willReturnSelf(); $this->modelRepository->afterGet( - $this->createMock(\Magento\Quote\Model\Cart\CartTotalRepository::class), - $quoteMock, - $cartId + $this->quoteTotalRepositoryMock, + $this->quoteTotalsMock, + self::STUB_CART_ID ); } } diff --git a/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout_customer_address.xml b/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout_customer_address.xml index fee3cb790a522..449f5feeafd9c 100644 --- a/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout_customer_address.xml +++ b/app/code/Magento/Multishipping/view/frontend/layout/multishipping_checkout_customer_address.xml @@ -13,6 +13,7 @@ <arguments> <argument name="attribute_data" xsi:type="object">Magento\Customer\Block\DataProviders\AddressAttributeData</argument> <argument name="post_code_config" xsi:type="object">Magento\Customer\Block\DataProviders\PostCodesPatternsAttributeData</argument> + <argument name="view_model" xsi:type="object">Magento\Customer\ViewModel\Address</argument> </arguments> </block> </referenceContainer> diff --git a/app/code/Magento/NewRelicReporting/Test/Mftf/Test/AdminCheckNewRelicSystemConfigDependencyTest.xml b/app/code/Magento/NewRelicReporting/Test/Mftf/Test/AdminCheckNewRelicSystemConfigDependencyTest.xml index c343f93de2c58..5b4b92559f355 100644 --- a/app/code/Magento/NewRelicReporting/Test/Mftf/Test/AdminCheckNewRelicSystemConfigDependencyTest.xml +++ b/app/code/Magento/NewRelicReporting/Test/Mftf/Test/AdminCheckNewRelicSystemConfigDependencyTest.xml @@ -25,7 +25,7 @@ </actionGroup> </before> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <actionGroup ref="AssertAdminNewRelicConfigFieldIsNotVisibleActionGroup" stepKey="checkingIfApiUrlIsNotVisible"> <argument name="config" value="{{AdminNewRelicConfigSystemSection.apiUrl}}"/> diff --git a/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/HttpPluginTest.php b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/HttpPluginTest.php new file mode 100644 index 0000000000000..e4c6426f9e868 --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/HttpPluginTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\NewRelicReporting\Test\Unit\Plugin; + +use Exception; +use Magento\Framework\App\Bootstrap; +use Magento\Framework\App\Http; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\NewRelicReporting\Model\Config as NewRelicConfig; +use Magento\NewRelicReporting\Model\NewRelicWrapper; +use Magento\NewRelicReporting\Plugin\HttpPlugin; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject as MockObject; + +/** + * Test coverage for \Magento\NewRelicReporting\Plugin\HttpPlugin + */ +class HttpPluginTest extends TestCase +{ + /** + * @var HttpPlugin + */ + private $httpPlugin; + + /** + * @var NewRelicConfig|MockObject + */ + private $configMock; + + /** + * @var NewRelicWrapper|MockObject + */ + private $newRelicWrapperMock; + + /** + * @var Http|MockObject + */ + private $httpMock; + + /** + * @var Bootstrap|MockObject + */ + private $bootstrapMock; + + /** + * @var Exception|MockObject + */ + private $exceptionMock; + + /** + * Set Up + */ + public function setUp(): void + { + $objectManager = new ObjectManager($this); + $this->configMock = $this->getMockBuilder(NewRelicConfig::class)->disableOriginalConstructor() + ->getMock(); + $this->newRelicWrapperMock = $this->createMock(NewRelicWrapper::class); + $this->httpMock = $this->createMock(Http::class); + $this->bootstrapMock = $this->createMock(Bootstrap::class); + $this->exceptionMock = $this->createMock(Exception::class); + + $this->httpPlugin = $objectManager->getObject( + HttpPlugin::class, + [ + 'config' => $this->configMock, + 'newRelicWrapper' => $this->newRelicWrapperMock, + ] + ); + } + + /** + * Tests the thrown exception is reported to New Relic + */ + public function testSuccessfullyReportingError(): void + { + $this->configMock->expects($this->once())->method('isNewRelicEnabled')->willReturn(true); + $this->newRelicWrapperMock->expects($this->once())->method('reportError'); + + $this->httpPlugin->beforeCatchException($this->httpMock, $this->bootstrapMock, $this->exceptionMock); + } + + /** + * Tests the thrown exception is not reported to New Relic + */ + public function testNotReportingException(): void + { + $this->configMock->expects($this->once())->method('isNewRelicEnabled')->willReturn(false); + $this->newRelicWrapperMock->expects($this->never())->method('reportError'); + + $this->httpPlugin->beforeCatchException($this->httpMock, $this->bootstrapMock, $this->exceptionMock); + } +} diff --git a/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php new file mode 100644 index 0000000000000..b2e75d0b435eb --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php @@ -0,0 +1,135 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\NewRelicReporting\Test\Unit\Plugin; + +use Magento\Framework\App\State; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\NewRelicReporting\Model\Config as NewRelicConfig; +use Magento\NewRelicReporting\Model\NewRelicWrapper; +use Magento\NewRelicReporting\Plugin\StatePlugin; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject as MockObject; +use Psr\Log\LoggerInterface; + +/** + * Test coverage for \Magento\NewRelicReporting\Plugin\StatePlugin + */ +class StatePluginTest extends TestCase +{ + /** + * @var string + */ + private const STUB_APP_NAME = 'app_name'; + + /** + * @var StatePlugin + */ + private $statePlugin; + + /** + * @var NewRelicConfig|MockObject + */ + private $configMock; + + /** + * @var NewRelicWrapper|MockObject + */ + private $newRelicWrapperMock; + + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var State|MockObject + */ + private $stateMock; + + /** + * Set Up + */ + public function setUp(): void + { + $objectManager = new ObjectManager($this); + $this->configMock = $this->getMockBuilder(NewRelicConfig::class)->disableOriginalConstructor() + ->getMock(); + $this->newRelicWrapperMock = $this->createMock(NewRelicWrapper::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->stateMock = $this->createMock(State::class); + + $this->statePlugin = $objectManager->getObject( + StatePlugin::class, + [ + 'config' => $this->configMock, + 'newRelicWrapper' => $this->newRelicWrapperMock, + 'logger' => $this->loggerMock, + ] + ); + } + + /** + * Tests setting the new relic app name + */ + public function testSuccessfullySettingAppName(): void + { + $this->configMock->expects($this->once())->method('isSeparateApps')->willReturn(true); + $this->configMock->expects($this->any())->method('getNewRelicAppName') + ->willReturn(static::STUB_APP_NAME); + $this->configMock->expects($this->once())->method('isNewRelicEnabled')->willReturn(true); + $this->stateMock->expects($this->once())->method('getAreaCode')->willReturn('frontend'); + $this->newRelicWrapperMock->expects($this->once())->method('setAppName'); + + $this->statePlugin->afterSetAreaCode($this->stateMock, static::STUB_APP_NAME); + } + + /** + * Tests not being able to set the New Relic app name + * + * @param bool $isSeparateApps + * @param string $newRelicAppName + * @param bool $enabled + * + * @dataProvider newRelicConfigDataProvider + */ + public function testSuccessfullySettingAreaCode(bool $isSeparateApps, string $newRelicAppName, bool $enabled): void + { + $this->configMock->expects($this->any())->method('isSeparateApps')->willReturn($isSeparateApps); + $this->configMock->expects($this->any())->method('getNewRelicAppName')->willReturn($newRelicAppName); + $this->configMock->expects($this->any())->method('isNewRelicEnabled')->willReturn($enabled); + $this->newRelicWrapperMock->expects($this->never())->method('setAppName'); + + $this->statePlugin->afterSetAreaCode($this->stateMock, static::STUB_APP_NAME); + } + + /** + * New relic configuration data provider + * + * @return array + */ + public function newRelicConfigDataProvider(): array + { + return [ + 'Separate apps config is disabled' => [ + false, + static::STUB_APP_NAME, + true + ], + 'Application name is not configured' => [ + true, + '', + true + ], + 'New Relic is disabled' => [ + true, + static::STUB_APP_NAME, + false + ] + ]; + } +} diff --git a/app/code/Magento/Newsletter/Block/Adminhtml/Subscriber.php b/app/code/Magento/Newsletter/Block/Adminhtml/Subscriber.php index 4d5165db68736..d05657c727192 100644 --- a/app/code/Magento/Newsletter/Block/Adminhtml/Subscriber.php +++ b/app/code/Magento/Newsletter/Block/Adminhtml/Subscriber.php @@ -11,13 +11,18 @@ */ namespace Magento\Newsletter\Block\Adminhtml; +use Magento\Backend\Block\Template; +use Magento\Backend\Block\Template\Context; use Magento\Newsletter\Model\ResourceModel\Queue\Collection; +use Magento\Newsletter\Model\ResourceModel\Queue\CollectionFactory; /** + * Newsletter Subscriber block + * * @api * @since 100.0.2 */ -class Subscriber extends \Magento\Backend\Block\Template +class Subscriber extends Template { /** * Queue collection @@ -32,34 +37,24 @@ class Subscriber extends \Magento\Backend\Block\Template protected $_template = 'Magento_Newsletter::subscriber/list.phtml'; /** - * @var \Magento\Newsletter\Model\ResourceModel\Queue\CollectionFactory + * @var CollectionFactory */ protected $_collectionFactory; /** - * @param \Magento\Backend\Block\Template\Context $context - * @param \Magento\Newsletter\Model\ResourceModel\Queue\CollectionFactory $collectionFactory + * @param Context $context + * @param CollectionFactory $collectionFactory * @param array $data */ public function __construct( - \Magento\Backend\Block\Template\Context $context, - \Magento\Newsletter\Model\ResourceModel\Queue\CollectionFactory $collectionFactory, + Context $context, + CollectionFactory $collectionFactory, array $data = [] ) { $this->_collectionFactory = $collectionFactory; parent::__construct($context, $data); } - /** - * Prepares block to render - * - * @return $this - */ - protected function _beforeToHtml() - { - return parent::_beforeToHtml(); - } - /** * Return queue collection with loaded neversent queues * @@ -68,7 +63,7 @@ protected function _beforeToHtml() public function getQueueCollection() { if ($this->_queueCollection === null) { - /** @var $this->_queueCollection \Magento\Newsletter\Model\ResourceModel\Queue\Collection */ + /** @var $this->_queueCollection Collection */ $this->_queueCollection = $this ->_collectionFactory ->create() diff --git a/app/code/Magento/Newsletter/Controller/Ajax/Status.php b/app/code/Magento/Newsletter/Controller/Ajax/Status.php new file mode 100644 index 0000000000000..5d36b7170738d --- /dev/null +++ b/app/code/Magento/Newsletter/Controller/Ajax/Status.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Controller\Ajax; + +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Json; +use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Validator\EmailAddress as EmailAddressValidator; +use Magento\Newsletter\Model\GuestSubscriptionChecker; +use Psr\Log\LoggerInterface; + +/** + * Newsletter subscription status verification controller. + */ +class Status extends Action implements HttpGetActionInterface +{ + /** + * @var EmailAddressValidator + */ + private $emailAddressValidator; + + /** + * @var GuestSubscriptionChecker + */ + private $guestSubscriptionChecker; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @param Context $context + * @param EmailAddressValidator $emailAddressValidator + * @param GuestSubscriptionChecker $guestSubscriptionChecker + * @param LoggerInterface $logger + */ + public function __construct( + Context $context, + EmailAddressValidator $emailAddressValidator, + GuestSubscriptionChecker $guestSubscriptionChecker, + LoggerInterface $logger + ) { + parent::__construct($context); + $this->emailAddressValidator = $emailAddressValidator; + $this->guestSubscriptionChecker = $guestSubscriptionChecker; + $this->logger = $logger; + } + + /** + * @inheritdoc + */ + public function execute() + { + $email = (string)$this->getRequest()->getParam('email'); + + $response = [ + 'subscribed' => false, + 'errors' => false, + ]; + try { + if (!empty($email) && $this->emailAddressValidator->isValid($email)) { + $response['subscribed'] = $this->guestSubscriptionChecker->isSubscribed($email); + } + } catch (LocalizedException | \DomainException $exception) { + $this->logger->error($exception->getMessage()); + $response['errors'] = true; + } + + /** @var Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + + return $resultJson->setData($response); + } +} diff --git a/app/code/Magento/Newsletter/Model/GuestSubscriptionChecker.php b/app/code/Magento/Newsletter/Model/GuestSubscriptionChecker.php new file mode 100644 index 0000000000000..8e8c68cfc7de5 --- /dev/null +++ b/app/code/Magento/Newsletter/Model/GuestSubscriptionChecker.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Model; + +use Magento\Framework\App\ResourceConnection; +use Magento\Store\Model\StoreManagerInterface; + +/** + * Checks guest subscription by email. + */ +class GuestSubscriptionChecker +{ + /** + * @var ResourceConnection + */ + private $resourceConnection; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param ResourceConnection $resourceConnection + * @param StoreManagerInterface $storeManager + */ + public function __construct(ResourceConnection $resourceConnection, StoreManagerInterface $storeManager) + { + $this->resourceConnection = $resourceConnection; + $this->storeManager = $storeManager; + } + + /** + * Check is subscribed by email + * + * @param string $subscriberEmail + * @return bool + */ + public function isSubscribed(string $subscriberEmail): bool + { + if (!empty($subscriberEmail)) { + $storeIds = $this->storeManager->getWebsite()->getStoreIds(); + $connection = $this->resourceConnection->getConnection(); + $select = $connection + ->select() + ->from($this->resourceConnection->getTableName('newsletter_subscriber')) + ->where('subscriber_email = ?', $subscriberEmail) + ->where('store_id IN (?)', $storeIds) + ->where('customer_id = 0') + ->limit(1); + + return (bool)$connection->fetchOne($select); + } + + return false; + } +} diff --git a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php index 60b279b659ca6..6bdaa40019f8a 100644 --- a/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php +++ b/app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php @@ -17,6 +17,7 @@ use Magento\Newsletter\Model\SubscriptionManagerInterface; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\Api\SearchResults; use Psr\Log\LoggerInterface; /** @@ -109,8 +110,9 @@ public function afterSave( CustomerInterface $result, CustomerInterface $customer ) { + /** @var Subscriber $subscriber */ $subscriber = $this->getSubscriber($result); - $subscribeStatus = $this->getIsSubscribedFromExtensionAttr($customer) ?? $subscriber->isSubscribed(); + $subscribeStatus = $this->getIsSubscribedFromExtensionAttributes($customer) ?? $subscriber->isSubscribed(); $needToUpdate = $this->isSubscriptionChanged($result, $subscriber, $subscribeStatus); /** @@ -118,7 +120,10 @@ public function afterSave( * and customer is already confirmed registration * than need to subscribe customer */ - if ((int)$subscriber->getStatus() === Subscriber::STATUS_UNCONFIRMED && empty($result->getConfirmation())) { + if ($subscriber->getId() + && (int)$subscriber->getStatus() === Subscriber::STATUS_UNCONFIRMED + && empty($result->getConfirmation()) + ) { $needToUpdate = true; $subscribeStatus = true; } @@ -129,7 +134,7 @@ public function afterSave( : $this->subscriptionManager->unsubscribeCustomer((int)$result->getId(), $storeId); $this->customerSubscriber[(int)$result->getId()] = $subscriber; } - $this->addIsSubscribedExtensionAttr($result, $subscriber->isSubscribed()); + $this->addIsSubscribedExtensionAttribute($result, $subscriber->isSubscribed()); return $result; } @@ -140,14 +145,14 @@ public function afterSave( * @param CustomerInterface $customer * @return bool|null */ - private function getIsSubscribedFromExtensionAttr(CustomerInterface $customer): ?bool + private function getIsSubscribedFromExtensionAttributes(CustomerInterface $customer): ?bool { - $newExtensionAttributes = $customer->getExtensionAttributes(); - if ($newExtensionAttributes === null || $newExtensionAttributes->getIsSubscribed() === null) { + $extensionAttributes = $customer->getExtensionAttributes(); + if ($extensionAttributes === null || $extensionAttributes->getIsSubscribed() === null) { return null; } - return (bool)$newExtensionAttributes->getIsSubscribed(); + return (bool)$extensionAttributes->getIsSubscribed(); } /** @@ -223,19 +228,40 @@ public function afterGetById(CustomerRepositoryInterface $subject, CustomerInter $extensionAttributes = $customer->getExtensionAttributes(); if ($extensionAttributes === null || $extensionAttributes->getIsSubscribed() === null) { $isSubscribed = $this->getSubscriber($customer)->isSubscribed(); - $this->addIsSubscribedExtensionAttr($customer, $isSubscribed); + $this->addIsSubscribedExtensionAttribute($customer, $isSubscribed); } return $customer; } + /** + * Add subscription status to customer list + * + * @param CustomerRepositoryInterface $subject + * @param SearchResults $searchResults + * @return SearchResults + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetList(CustomerRepositoryInterface $subject, SearchResults $searchResults): SearchResults + { + foreach ($searchResults->getItems() as $customer) { + /** @var CustomerExtensionInterface $extensionAttributes */ + $extensionAttributes = $customer->getExtensionAttributes(); + + $isSubscribed = (int) $extensionAttributes->getIsSubscribed() === Subscriber::STATUS_SUBSCRIBED ?: false; + $extensionAttributes->setIsSubscribed($isSubscribed); + } + + return $searchResults; + } + /** * Set Is Subscribed extension attribute * * @param CustomerInterface $customer * @param bool $isSubscribed */ - private function addIsSubscribedExtensionAttr(CustomerInterface $customer, bool $isSubscribed): void + private function addIsSubscribedExtensionAttribute(CustomerInterface $customer, bool $isSubscribed): void { $extensionAttributes = $customer->getExtensionAttributes(); if ($extensionAttributes === null) { diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml index 4992a36c0b3cb..a763f43d9e4d1 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddImageToWYSIWYGNewsletterTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MAGETWO-84377"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -58,7 +58,7 @@ <closeTab stepKey="closeTab"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index 958340671ac43..ff2e2a84a612e 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -18,7 +18,7 @@ <severity value="AVERAGE"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -100,7 +100,7 @@ <closeTab stepKey="closeTab"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 29c125a52c9e2..73880f283677d 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MC-6070"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -55,7 +55,7 @@ <closeTab stepKey="closeTab"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterQueueNavigateMenuTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterQueueNavigateMenuTest.xml index 31da588250a0a..c094117870712 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterQueueNavigateMenuTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterQueueNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToNewsletterQueuePage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterSubscribersNavigateMenuTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterSubscribersNavigateMenuTest.xml index 8ced2690322f8..a5046b6fa4b71 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterSubscribersNavigateMenuTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterSubscribersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToNewsletterSubscribersPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterTemplateNavigateMenuTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterTemplateNavigateMenuTest.xml index ca994aa1d6269..4c12765ebc2a0 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterTemplateNavigateMenuTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminMarketingNewsletterTemplateNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToNewsletterTemplatePage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminNameEmptyForGuestTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminNameEmptyForGuestTest.xml index 07c7cc050d5cf..a90a035b25726 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminNameEmptyForGuestTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminNameEmptyForGuestTest.xml @@ -11,6 +11,7 @@ <test name="AdminNameEmptyForGuestTest"> <annotations> <features value="Newsletter"/> + <stories value="Newsletter Subscribers grid"/> <group value="Newsletter"/> <title value="Empty name for Guest Customer"/> <description value="'Customer First Name' and 'Customer Last Name' should be empty for Guest Customer in Newsletter Subscribers Grid"/> @@ -18,11 +19,11 @@ </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminReportsNewsletterProblemReportsNavigateMenuTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminReportsNewsletterProblemReportsNavigateMenuTest.xml index 3891b90536a17..9765a65cd60db 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminReportsNewsletterProblemReportsNavigateMenuTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminReportsNewsletterProblemReportsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToNewsletterProblemsReportPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifySubscribedNewsletterDisplayedTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifySubscribedNewsletterDisplayedTest.xml index 200eb0e49f5b2..a568fb1799ac2 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifySubscribedNewsletterDisplayedTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifySubscribedNewsletterDisplayedTest.xml @@ -21,7 +21,7 @@ <before> <!--Log in to Magento as admin.--> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite"> <argument name="newWebsiteName" value="Second"/> <argument name="websiteCode" value="Base2"/> @@ -49,7 +49,7 @@ </actionGroup> <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Go to store front (default) and click Create an Account.--> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml index 0c20357127e6d..3a247402c111d 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnNewsletterTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MAGETWO-84683"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> </before> @@ -49,7 +49,7 @@ <closeTab stepKey="closeTab"/> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php index 52b3df8cb8aa6..4dbaa93b1d134 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php @@ -124,10 +124,14 @@ public function testAfterSave(?int $originalStatus, ?bool $newValue, ?bool $expe ->method('loadByCustomer') ->with($customerId, $websiteId) ->willReturnSelf(); - $subscriber->expects($this->once()) - ->method('loadBySubscriberEmail') - ->with($customerEmail, $websiteId) - ->willReturnSelf(); + if ($originalStatus !== null && $originalStatus === Subscriber::STATUS_UNCONFIRMED) { + $subscriber->method('getId')->willReturn(1); + } else { + $subscriber->expects($this->once()) + ->method('loadBySubscriberEmail') + ->with($customerEmail, $websiteId) + ->willReturnSelf(); + } $this->subscriberFactory->method('create')->willReturn($subscriber); $customerExtension = $this->createPartialMock(CustomerExtensionInterface::class, ['getIsSubscribed']); @@ -162,23 +166,25 @@ public function testAfterSave(?int $originalStatus, ?bool $newValue, ?bool $expe } /** + * Data provider for testAfterSave() + * * @return array */ - public function afterSaveDataProvider() + public function afterSaveDataProvider(): array { return [ - [null, null, null], - [null, true, true], - [null, false, null], - [Subscriber::STATUS_SUBSCRIBED, null, null], - [Subscriber::STATUS_SUBSCRIBED, true, null], - [Subscriber::STATUS_SUBSCRIBED, false, false], - [Subscriber::STATUS_UNSUBSCRIBED, null, null], - [Subscriber::STATUS_UNSUBSCRIBED, true, true], - [Subscriber::STATUS_UNSUBSCRIBED, false, null], - [Subscriber::STATUS_UNCONFIRMED, null, true], - [Subscriber::STATUS_UNCONFIRMED, true, true], - [Subscriber::STATUS_UNCONFIRMED, false, true], + 'missing_previous_and_new_status' => [null, null, null], + 'missing_previous_status_and_subscribe' => [null, true, true], + 'new_unsubscribed_value_and_missing_previous_status' => [null, false, null], + 'previous_subscribed_status_without_new_value' => [Subscriber::STATUS_SUBSCRIBED, null, null], + 'same_subscribed_previous_and_new_status' => [Subscriber::STATUS_SUBSCRIBED, true, null], + 'unsubscribe_previously_subscribed_customer' => [Subscriber::STATUS_SUBSCRIBED, false, false], + 'previously_unsubscribed_status_without_new_value' => [Subscriber::STATUS_UNSUBSCRIBED, null, null], + 'subscribe_previously_unsubscribed_customer' => [Subscriber::STATUS_UNSUBSCRIBED, true, true], + 'same_unsubscribed_previous_and_new_status' => [Subscriber::STATUS_UNSUBSCRIBED, false, null], + 'previous_unconfirmed_status_without_new_value' => [Subscriber::STATUS_UNCONFIRMED, null, true], + 'subscribe_previously_unconfirmed_status' => [Subscriber::STATUS_UNCONFIRMED, true, true], + 'unsubscribe_previously_unconfirmed_status' => [Subscriber::STATUS_UNCONFIRMED, false, true], ]; } diff --git a/app/code/Magento/Newsletter/etc/extension_attributes.xml b/app/code/Magento/Newsletter/etc/extension_attributes.xml index 50f46af5c033b..09925024e97d5 100644 --- a/app/code/Magento/Newsletter/etc/extension_attributes.xml +++ b/app/code/Magento/Newsletter/etc/extension_attributes.xml @@ -8,6 +8,10 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> - <attribute code="is_subscribed" type="boolean" /> + <attribute code="is_subscribed" type="boolean" > + <join reference_table="newsletter_subscriber" reference_field="customer_id" join_on_field="entity_id"> + <field>subscriber_status</field> + </join> + </attribute> </extension_attributes> </config> diff --git a/app/code/Magento/Newsletter/view/frontend/layout/customer_account_create.xml b/app/code/Magento/Newsletter/view/frontend/layout/customer_account_create.xml new file mode 100644 index 0000000000000..98c6daa62474a --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/layout/customer_account_create.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="customer_form_register"> + <block name="customer.form.register.newsletter" template="Magento_Newsletter::form/register/newsletter.phtml"/> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Newsletter/view/frontend/requirejs-config.js b/app/code/Magento/Newsletter/view/frontend/requirejs-config.js new file mode 100644 index 0000000000000..a63d47a0cf732 --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/requirejs-config.js @@ -0,0 +1,13 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +var config = { + map: { + '*': { + subscriptionStatusResolver: 'Magento_Newsletter/js/subscription-status-resolver', + newsletterSignUp: 'Magento_Newsletter/js/newsletter-sign-up' + } + } +}; diff --git a/app/code/Magento/Newsletter/view/frontend/templates/form/register/newsletter.phtml b/app/code/Magento/Newsletter/view/frontend/templates/form/register/newsletter.phtml new file mode 100644 index 0000000000000..3034b6550e9a6 --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/templates/form/register/newsletter.phtml @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +?> +<script type="text/x-magento-init"> +{ + "#email_address": { + "newsletterSignUp": { + "signUpElement": "#is_subscribed", + "submitButton": ".form-create-account button[type='submit']" + } + } +} +</script> diff --git a/app/code/Magento/Newsletter/view/frontend/web/js/newsletter-sign-up.js b/app/code/Magento/Newsletter/view/frontend/web/js/newsletter-sign-up.js new file mode 100644 index 0000000000000..fa1d01ed2ed4e --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/web/js/newsletter-sign-up.js @@ -0,0 +1,63 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'uiElement', + 'mage/url', + 'subscriptionStatusResolver', + 'mage/validation' +], function ($, Component, urlBuilder, subscriptionStatusResolver) { + 'use strict'; + + return Component.extend({ + + defaults: { + signUpElement: '', + submitButton: '', + element: null + }, + + /** @inheritdoc */ + initialize: function (config, element) { + this._super(); + this.element = element; + $(element).on('change', $.proxy(this.updateSignUpStatus, this)); + this.updateSignUpStatus(); + }, + + /** + * Send status request and update subscription element according to result. + */ + updateSignUpStatus: function () { + var element = $(this.element), + email = element.val(), + self = this, + newsletterSubscription; + + if ($(self.signUpElement).is(':checked')) { + return; + } + + if (!email || !$.validator.methods['validate-email'].call(this, email, element)) { + return; + } + + newsletterSubscription = $.Deferred(); + + $(self.submitButton).prop('disabled', true); + + subscriptionStatusResolver(email, newsletterSubscription); + + $.when(newsletterSubscription).done(function (isSubscribed) { + if (isSubscribed) { + $(self.signUpElement).prop('checked', true); + } + }).always(function () { + $(self.submitButton).prop('disabled', false); + }); + } + }); +}); diff --git a/app/code/Magento/Newsletter/view/frontend/web/js/subscription-status-resolver.js b/app/code/Magento/Newsletter/view/frontend/web/js/subscription-status-resolver.js new file mode 100644 index 0000000000000..13a4fc3e45f1c --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/web/js/subscription-status-resolver.js @@ -0,0 +1,28 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'mage/url' +], function ($, urlBuilder) { + 'use strict'; + + return function (email, deferred) { + return $.getJSON( + urlBuilder.build('newsletter/ajax/status'), + { + email: email + } + ).done(function (response) { + if (response.errors) { + deferred.reject(); + } else { + deferred.resolve(response.subscribed); + } + }).fail(function () { + deferred.reject(); + }); + }; +}); diff --git a/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php b/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php index d7cad6b62e993..234bec96d46d1 100644 --- a/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php +++ b/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php @@ -3,9 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\OfflinePayments\Observer; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\OfflinePayments\Model\Banktransfer; use Magento\OfflinePayments\Model\Cashondelivery; @@ -19,10 +21,10 @@ class BeforeOrderPaymentSaveObserver implements ObserverInterface /** * Sets current instructions for bank transfer account * - * @param \Magento\Framework\Event\Observer $observer + * @param Observer $observer * @return void */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { /** @var \Magento\Sales\Model\Order\Payment $payment */ $payment = $observer->getEvent()->getPayment(); @@ -34,15 +36,22 @@ public function execute(\Magento\Framework\Event\Observer $observer) && empty($payment->getAdditionalInformation('instructions'))) { $payment->setAdditionalInformation( 'instructions', - $payment->getMethodInstance()->getInstructions() + $payment->getMethodInstance()->getConfigData( + 'instructions', + $payment->getOrder()->getStoreId() + ) ); } elseif ($payment->getMethod() === Checkmo::PAYMENT_METHOD_CHECKMO_CODE) { $methodInstance = $payment->getMethodInstance(); - if (!empty($methodInstance->getPayableTo())) { - $payment->setAdditionalInformation('payable_to', $methodInstance->getPayableTo()); + $storeId = $payment->getOrder()->getStoreId(); + + $payableTo = $methodInstance->getConfigData('payable_to', $storeId); + if (!empty($payableTo)) { + $payment->setAdditionalInformation('payable_to', $payableTo); } - if (!empty($methodInstance->getMailingAddress())) { - $payment->setAdditionalInformation('mailing_address', $methodInstance->getMailingAddress()); + $mailingAddress = $methodInstance->getConfigData('mailing_address', $storeId); + if (!empty($mailingAddress)) { + $payment->setAdditionalInformation('mailing_address', $mailingAddress); } } } diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php index 0b482a805175a..18f57269b616b 100644 --- a/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php +++ b/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php @@ -10,32 +10,44 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\OfflinePayments\Model\Banktransfer; use Magento\OfflinePayments\Model\Cashondelivery; +use Magento\OfflinePayments\Model\Checkmo; use Magento\OfflinePayments\Observer\BeforeOrderPaymentSaveObserver; +use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment; -use PHPUnit_Framework_MockObject_MockObject as MockObject; -use Magento\OfflinePayments\Model\Checkmo; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; -class BeforeOrderPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase +/** + * Test class for \Magento\OfflinePayments\Observer\BeforeOrderPaymentSaveObserver + */ +class BeforeOrderPaymentSaveObserverTest extends TestCase { + private const STORE_ID = 1; + /** * @var BeforeOrderPaymentSaveObserver */ - protected $_model; + private $model; /** * @var Payment|MockObject */ - private $payment; + private $paymentMock; /** * @var Event|MockObject */ - private $event; + private $eventMock; /** * @var Observer|MockObject */ - private $observer; + private $observerMock; + + /** + * @var Order|MockObject + */ + private $orderMock; /** * @inheritdoc @@ -43,40 +55,50 @@ class BeforeOrderPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase protected function setUp() { $objectManagerHelper = new ObjectManager($this); - $this->payment = $this->getMockBuilder(Payment::class) + $this->paymentMock = $this->getMockBuilder(Payment::class) ->disableOriginalConstructor() ->getMock(); - $this->event = $this->getMockBuilder(Event::class) + $this->eventMock = $this->getMockBuilder(Event::class) ->disableOriginalConstructor() ->setMethods(['getPayment']) ->getMock(); - $this->event->expects(self::once()) + $this->eventMock->expects(self::once()) ->method('getPayment') - ->willReturn($this->payment); + ->willReturn($this->paymentMock); - $this->observer = $this->getMockBuilder(Observer::class) + $this->observerMock = $this->getMockBuilder(Observer::class) ->disableOriginalConstructor() ->getMock(); - $this->observer->expects(self::once()) + $this->observerMock->expects(self::once()) ->method('getEvent') - ->willReturn($this->event); + ->willReturn($this->eventMock); + + $this->orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + $this->orderMock->method('getStoreId') + ->willReturn(static::STORE_ID); - $this->_model = $objectManagerHelper->getObject(BeforeOrderPaymentSaveObserver::class); + $this->paymentMock->method('getOrder') + ->willReturn($this->orderMock); + + $this->model = $objectManagerHelper->getObject(BeforeOrderPaymentSaveObserver::class); } /** + * Checks a case when payment method is either bank transfer or cash on delivery * @param string $methodCode * @dataProvider dataProviderBeforeOrderPaymentSaveWithInstructions */ public function testBeforeOrderPaymentSaveWithInstructions($methodCode) { - $this->payment->expects(self::once()) + $this->paymentMock->expects(self::once()) ->method('getMethod') ->willReturn($methodCode); - $this->payment->expects(self::once()) + $this->paymentMock->expects(self::once()) ->method('setAdditionalInformation') ->with('instructions', 'payment configuration'); $method = $this->getMockBuilder(Banktransfer::class) @@ -84,13 +106,14 @@ public function testBeforeOrderPaymentSaveWithInstructions($methodCode) ->getMock(); $method->expects(self::once()) - ->method('getInstructions') + ->method('getConfigData') + ->with('instructions', static::STORE_ID) ->willReturn('payment configuration'); - $this->payment->expects(self::once()) + $this->paymentMock->expects(self::once()) ->method('getMethodInstance') ->willReturn($method); - $this->_model->execute($this->observer); + $this->model->execute($this->observerMock); } /** @@ -106,33 +129,37 @@ public function dataProviderBeforeOrderPaymentSaveWithInstructions() ]; } + /** + * Checks a case when payment method is Check Money + */ public function testBeforeOrderPaymentSaveWithCheckmo() { - $this->payment->expects(self::exactly(2)) + $this->paymentMock->expects(self::exactly(2)) ->method('getMethod') ->willReturn(Checkmo::PAYMENT_METHOD_CHECKMO_CODE); - $this->payment->expects(self::exactly(2)) + $this->paymentMock->expects(self::exactly(2)) ->method('setAdditionalInformation') ->willReturnMap( [ - ['payable_to', 'payable to', $this->payment], - ['mailing_address', 'mailing address', $this->payment], + ['payable_to', 'payable to', $this->paymentMock], + ['mailing_address', 'mailing address', $this->paymentMock], ] ); $method = $this->getMockBuilder(Checkmo::class) ->disableOriginalConstructor() ->getMock(); - $method->expects(self::exactly(2)) - ->method('getPayableTo') - ->willReturn('payable to'); - $method->expects(self::exactly(2)) - ->method('getMailingAddress') - ->willReturn('mailing address'); - $this->payment->expects(self::once()) + $method->method('getConfigData') + ->willReturnMap( + [ + ['payable_to', static::STORE_ID, 'payable to'], + ['mailing_address', static::STORE_ID, 'mailing address'] + ] + ); + $this->paymentMock->expects(self::once()) ->method('getMethodInstance') ->willReturn($method); - $this->_model->execute($this->observer); + $this->model->execute($this->observerMock); } /** @@ -141,36 +168,40 @@ public function testBeforeOrderPaymentSaveWithCheckmo() */ public function testBeforeOrderPaymentSaveWithCheckmoWithoutConfig() { - $this->payment->expects(self::exactly(2)) + $this->paymentMock->expects(self::exactly(2)) ->method('getMethod') ->willReturn(Checkmo::PAYMENT_METHOD_CHECKMO_CODE); - $this->payment->expects(self::never()) + $this->paymentMock->expects(self::never()) ->method('setAdditionalInformation'); $method = $this->getMockBuilder(Checkmo::class) ->disableOriginalConstructor() ->getMock(); - $method->expects(self::once()) - ->method('getPayableTo') - ->willReturn(null); - $method->expects(self::once()) - ->method('getMailingAddress') - ->willReturn(null); - $this->payment->expects(self::once()) + $method->method('getConfigData') + ->willReturnMap( + [ + ['payable_to', static::STORE_ID, null], + ['mailing_address', static::STORE_ID, null] + ] + ); + $this->paymentMock->expects(self::once()) ->method('getMethodInstance') ->willReturn($method); - $this->_model->execute($this->observer); + $this->model->execute($this->observerMock); } + /** + * Checks a case with payment method not handled by observer + */ public function testBeforeOrderPaymentSaveWithOthers() { - $this->payment->expects(self::exactly(2)) + $this->paymentMock->expects(self::exactly(2)) ->method('getMethod') ->willReturn('somepaymentmethod'); - $this->payment->expects(self::never()) + $this->paymentMock->expects(self::never()) ->method('setAdditionalInformation'); - $this->_model->execute($this->observer); + $this->model->execute($this->observerMock); } /** @@ -179,17 +210,16 @@ public function testBeforeOrderPaymentSaveWithOthers() */ public function testBeforeOrderPaymentSaveWithInstructionsAlreadySet($methodCode) { - $this->payment - ->method('getMethod') + $this->paymentMock->method('getMethod') ->willReturn($methodCode); - $this->payment->expects(self::once()) + $this->paymentMock->expects(self::once()) ->method('getAdditionalInformation') ->willReturn('Test'); - $this->payment->expects(self::never()) + $this->paymentMock->expects(self::never()) ->method('setAdditionalInformation'); - $this->_model->execute($this->observer); + $this->model->execute($this->observerMock); } } diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php index 46c46243fed5c..bbc199c91263a 100644 --- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php +++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php @@ -141,7 +141,9 @@ public function collectRates(RateRequest $request) } } $oldValue = $request->getPackageValue(); - $request->setPackageValue($oldValue - $freePackageValue); + $newPackageValue = $oldValue - $freePackageValue; + $request->setPackageValue($newPackageValue); + $request->setPackageValueWithDiscount($newPackageValue); } if (!$request->getConditionName()) { diff --git a/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php b/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php index bf958707dde49..a6949cccc1add 100644 --- a/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php +++ b/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php @@ -6,6 +6,9 @@ namespace Magento\PageCache\Model\App\Response; +use Magento\Framework\App\PageCache\NotCacheableInterface; +use Magento\Framework\App\Response\Http as HttpResponse; + /** * HTTP response plugin for frontend. */ @@ -14,14 +17,15 @@ class HttpPlugin /** * Set proper value of X-Magento-Vary cookie. * - * @param \Magento\Framework\App\Response\Http $subject + * @param HttpResponse $subject * @return void */ - public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject) + public function beforeSendResponse(HttpResponse $subject) { - if ($subject instanceof \Magento\Framework\App\PageCache\NotCacheableInterface) { + if ($subject instanceof NotCacheableInterface || $subject->headersSent()) { return; } + $subject->sendVary(); } } diff --git a/app/code/Magento/PageCache/Observer/FlushAllCache.php b/app/code/Magento/PageCache/Observer/FlushAllCache.php index 0a45ebf265715..aca9fc5e2a8c0 100644 --- a/app/code/Magento/PageCache/Observer/FlushAllCache.php +++ b/app/code/Magento/PageCache/Observer/FlushAllCache.php @@ -1,18 +1,25 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\PageCache\Observer; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\PageCache\Cache; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +/** + * Observer used to flush all caches with built-in full page cache + */ class FlushAllCache implements ObserverInterface { /** - * @var \Magento\Framework\App\PageCache\Cache + * @var Cache * * @deprecated 100.1.0 */ @@ -21,48 +28,42 @@ class FlushAllCache implements ObserverInterface /** * Application config object * - * @var \Magento\PageCache\Model\Config + * @var Config */ protected $_config; /** - * @var \Magento\PageCache\Model\Cache\Type + * @var Type */ private $fullPageCache; /** - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Cache $cache + * @param Config $config + * @param Cache $cache + * @param Type $fullPageCache */ - public function __construct(\Magento\PageCache\Model\Config $config, \Magento\Framework\App\PageCache\Cache $cache) - { + public function __construct( + Config $config, + Cache $cache, + Type $fullPageCache + ) { $this->_config = $config; $this->_cache = $cache; + $this->fullPageCache = $fullPageCache; } /** * Flash Built-In cache - * @param \Magento\Framework\Event\Observer $observer + * + * @param Observer $observer + * * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - if ($this->_config->getType() == \Magento\PageCache\Model\Config::BUILT_IN) { - $this->getCache()->clean(); - } - } - - /** - * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547 - * - * @return \Magento\PageCache\Model\Cache\Type - */ - private function getCache() + public function execute(Observer $observer) { - if (!$this->fullPageCache) { - $this->fullPageCache = ObjectManager::getInstance()->get(\Magento\PageCache\Model\Cache\Type::class); + if ($this->_config->getType() == Config::BUILT_IN) { + $this->fullPageCache->clean(); } - return $this->fullPageCache; } } diff --git a/app/code/Magento/PageCache/Observer/FlushCacheByTags.php b/app/code/Magento/PageCache/Observer/FlushCacheByTags.php index 8ce26f7d31781..778557ee0dd2f 100644 --- a/app/code/Magento/PageCache/Observer/FlushCacheByTags.php +++ b/app/code/Magento/PageCache/Observer/FlushCacheByTags.php @@ -1,18 +1,27 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\PageCache\Observer; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\Cache\Tag\Resolver; +use Magento\Framework\App\PageCache\Cache; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Zend_Cache; +/** + * Observer used to cache by tags when using built-in full page cache + */ class FlushCacheByTags implements ObserverInterface { /** - * @var \Magento\Framework\App\PageCache\Cache + * @var Cache * * @deprecated 100.1.0 */ @@ -21,78 +30,59 @@ class FlushCacheByTags implements ObserverInterface /** * Application config object * - * @var \Magento\PageCache\Model\Config + * @var Config */ protected $_config; /** - * @var \Magento\PageCache\Model\Cache\Type + * @var Type */ private $fullPageCache; /** * Invalidation tags resolver * - * @var \Magento\Framework\App\Cache\Tag\Resolver + * @var Resolver */ private $tagResolver; /** - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\PageCache\Cache $cache + * @param Config $config + * @param Cache $cache + * @param Type $fullPageCache + * @param Resolver $tagResolver */ - public function __construct(\Magento\PageCache\Model\Config $config, \Magento\Framework\App\PageCache\Cache $cache) - { + public function __construct( + Config $config, + Cache $cache, + Type $fullPageCache, + Resolver $tagResolver + ) { $this->_config = $config; $this->_cache = $cache; + $this->fullPageCache = $fullPageCache; + $this->tagResolver = $tagResolver; } /** - * If Built-In caching is enabled it collects array of tags - * of incoming object and asks to clean cache. + * If Built-In caching is enabled it collects array of tags of incoming object and asks to clean cache. + * + * @param Observer $observer * - * @param \Magento\Framework\Event\Observer $observer * @return void */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { - if ($this->_config->getType() == \Magento\PageCache\Model\Config::BUILT_IN && $this->_config->isEnabled()) { + if ($this->_config->getType() == Config::BUILT_IN && $this->_config->isEnabled()) { $object = $observer->getEvent()->getObject(); if (!is_object($object)) { return; } - $tags = $this->getTagResolver()->getTags($object); + $tags = $this->tagResolver->getTags($object); if (!empty($tags)) { - $this->getCache()->clean(\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array_unique($tags)); + $this->fullPageCache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array_unique($tags)); } } } - - /** - * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547 - * - * - * @return \Magento\PageCache\Model\Cache\Type - */ - private function getCache() - { - if (!$this->fullPageCache) { - $this->fullPageCache = ObjectManager::getInstance()->get(\Magento\PageCache\Model\Cache\Type::class); - } - return $this->fullPageCache; - } - - /** - * @deprecated 100.1.2 - * @return \Magento\Framework\App\Cache\Tag\Resolver - */ - private function getTagResolver() - { - if ($this->tagResolver === null) { - $this->tagResolver = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\App\Cache\Tag\Resolver::class); - } - return $this->tagResolver; - } } diff --git a/app/code/Magento/PageCache/Test/Mftf/Test/AdminFrontendAreaSessionMustNotAffectAdminAreaTest.xml b/app/code/Magento/PageCache/Test/Mftf/Test/AdminFrontendAreaSessionMustNotAffectAdminAreaTest.xml index 375211e5f2f51..c94eed9dc6a57 100644 --- a/app/code/Magento/PageCache/Test/Mftf/Test/AdminFrontendAreaSessionMustNotAffectAdminAreaTest.xml +++ b/app/code/Magento/PageCache/Test/Mftf/Test/AdminFrontendAreaSessionMustNotAffectAdminAreaTest.xml @@ -40,7 +40,7 @@ </createData> <magentoCLI command="cache:clean" arguments="full_page" stepKey="clearCache"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> <resetCookie userInput="PHPSESSID" stepKey="resetSessionCookie"/> </before> @@ -54,7 +54,7 @@ <deleteData createDataKey="createCategoryB" stepKey="deleteCategoryB"/> <deleteData createDataKey="createCategoryA" stepKey="deleteCategoryA"/> - <actionGroup ref="logout" stepKey="logoutAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAdmin"/> </after> <!-- 1. Login as admin --> diff --git a/app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php index 59591c8ee957f..6f8f12098dda8 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php @@ -3,37 +3,63 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\PageCache\Test\Unit\Model\App\Response; +use Magento\Framework\App\Response\Http as HttpResponse; +use Magento\MediaStorage\Model\File\Storage\Response as FileResponse; use Magento\PageCache\Model\App\Response\HttpPlugin; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; -class HttpPluginTest extends \PHPUnit\Framework\TestCase +/** + * Tests \Magento\PageCache\Model\App\Response\HttpPlugin. + */ +class HttpPluginTest extends TestCase { /** - * @param \Magento\Framework\App\Response\FileInterface $responseInstanceClass + * @var HttpPlugin + */ + private $httpPlugin; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->httpPlugin = new HttpPlugin(); + } + + /** + * @param string $responseClass + * @param bool $headersSent * @param int $sendVaryCalled + * @return void * * @dataProvider beforeSendResponseDataProvider */ - public function testBeforeSendResponse($responseInstanceClass, $sendVaryCalled) + public function testBeforeSendResponse(string $responseClass, bool $headersSent, int $sendVaryCalled): void { - /** @var \Magento\Framework\App\Response\Http | \PHPUnit_Framework_MockObject_MockObject $responseMock */ - $responseMock = $this->createMock($responseInstanceClass); - $responseMock->expects($this->exactly($sendVaryCalled)) - ->method('sendVary'); - $plugin = new HttpPlugin(); - $plugin->beforeSendResponse($responseMock); + /** @var HttpResponse|MockObject $responseMock */ + $responseMock = $this->createMock($responseClass); + $responseMock->expects($this->any())->method('headersSent')->willReturn($headersSent); + $responseMock->expects($this->exactly($sendVaryCalled))->method('sendVary'); + + $this->httpPlugin->beforeSendResponse($responseMock); } /** * @return array */ - public function beforeSendResponseDataProvider() + public function beforeSendResponseDataProvider(): array { return [ - [\Magento\Framework\App\Response\Http::class, 1], - [\Magento\MediaStorage\Model\File\Storage\Response::class, 0] + 'http_response_headers_not_sent' => [HttpResponse::class, false, 1], + 'http_response_headers_sent' => [HttpResponse::class, true, 0], + 'file_response_headers_not_sent' => [FileResponse::class, false, 0], + 'file_response_headers_sent' => [FileResponse::class, true, 0], ]; } } diff --git a/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php b/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php index 27e1da5a9f144..a0fa99035c8b0 100644 --- a/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Observer/FlushAllCacheTest.php @@ -1,48 +1,61 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\PageCache\Test\Unit\Observer; -class FlushAllCacheTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\PageCache\Observer\FlushAllCache */ - private $_model; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Magento\PageCache\Observer\FlushAllCache; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Config */ - private $_configMock; +/** + * Test class for \Magento\PageCache\Observer\FlushAllCache + */ +class FlushAllCacheTest extends TestCase +{ + /** + * @var FlushAllCache + */ + private $model; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\PageCache\Cache */ - private $_cacheMock; + /** + * @var Config|MockObject + */ + private $configMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Event\Observer */ + /** + * @var Observer|MockObject + */ private $observerMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Cache\Type */ + /** + * @var Type|MockObject + */ private $fullPageCacheMock; /** - * Set up all mocks and data for test + * @inheritDoc */ protected function setUp() { - $this->_configMock = $this->createPartialMock(\Magento\PageCache\Model\Config::class, ['getType', 'isEnabled']); - $this->_cacheMock = $this->createPartialMock(\Magento\Framework\App\PageCache\Cache::class, ['clean']); - $this->fullPageCacheMock = $this->createPartialMock(\Magento\PageCache\Model\Cache\Type::class, ['clean']); - $this->observerMock = $this->createMock(\Magento\Framework\Event\Observer::class); + $this->configMock = $this->createPartialMock(Config::class, ['getType', 'isEnabled']); + $this->fullPageCacheMock = $this->createPartialMock(Type::class, ['clean']); + $this->observerMock = $this->createMock(Observer::class); - $this->_model = new \Magento\PageCache\Observer\FlushAllCache( - $this->_configMock, - $this->_cacheMock + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + FlushAllCache::class, + [ + 'config' => $this->configMock, + 'fullPageCache' => $this->fullPageCacheMock + ] ); - - $reflection = new \ReflectionClass(\Magento\PageCache\Observer\FlushAllCache::class); - $reflectionProperty = $reflection->getProperty('fullPageCache'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->_model, $this->fullPageCacheMock); } /** @@ -50,15 +63,32 @@ protected function setUp() */ public function testExecute() { - $this->_configMock->expects( + $this->configMock->expects( $this->once() )->method( 'getType' - )->will( - $this->returnValue(\Magento\PageCache\Model\Config::BUILT_IN) + )->willReturn( + Config::BUILT_IN ); $this->fullPageCacheMock->expects($this->once())->method('clean'); - $this->_model->execute($this->observerMock); + $this->model->execute($this->observerMock); + } + + /** + * Test case for flushing all the cache with varnish enabled + */ + public function testExecuteWithVarnish() + { + $this->configMock->expects( + $this->once() + )->method( + 'getType' + )->willReturn( + Config::VARNISH + ); + + $this->fullPageCacheMock->expects($this->never())->method('clean'); + $this->model->execute($this->observerMock); } } diff --git a/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php b/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php index 8019c6b2e810f..cc3df162fd35a 100644 --- a/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Observer/FlushCacheByTagsTest.php @@ -1,51 +1,66 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\PageCache\Test\Unit\Observer; -class FlushCacheByTagsTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\PageCache\Observer\FlushCacheByTags */ - protected $_model; +use Magento\Framework\App\Cache\Tag\Resolver; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\PageCache\Model\Cache\Type; +use Magento\PageCache\Model\Config; +use Magento\PageCache\Observer\FlushCacheByTags; +use Magento\Store\Model\Store; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Config */ - protected $_configMock; +/** + * Test class for \Magento\PageCache\Observer\FlushCacheByTags + */ +class FlushCacheByTagsTest extends TestCase +{ + /** + * @var FlushCacheByTags + */ + private $model; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\PageCache\Cache */ - protected $_cacheMock; + /** + * @var Config|MockObject + */ + private $configMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Cache\Type */ + /** + * @var Type|MockObject + */ private $fullPageCacheMock; - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Cache\Tag\Resolver */ - private $tagResolver; + /** + * @var Resolver|MockObject + */ + private $tagResolverMock; /** - * Set up all mocks and data for test + * @inheritDoc */ protected function setUp() { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_configMock = $this->createPartialMock(\Magento\PageCache\Model\Config::class, ['getType', 'isEnabled']); - $this->_cacheMock = $this->createPartialMock(\Magento\Framework\App\PageCache\Cache::class, ['clean']); - $this->fullPageCacheMock = $this->createPartialMock(\Magento\PageCache\Model\Cache\Type::class, ['clean']); - - $this->_model = new \Magento\PageCache\Observer\FlushCacheByTags( - $this->_configMock, - $this->_cacheMock + $this->configMock = $this->createPartialMock(Config::class, ['getType', 'isEnabled']); + $this->fullPageCacheMock = $this->createPartialMock(Type::class, ['clean']); + + $this->tagResolverMock = $this->createMock(Resolver::class); + + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject( + FlushCacheByTags::class, + [ + 'config' => $this->configMock, + 'fullPageCache' => $this->fullPageCacheMock, + 'tagResolver' => $this->tagResolverMock + ] ); - - $this->tagResolver = $this->createMock(\Magento\Framework\App\Cache\Tag\Resolver::class); - - $helper->setBackwardCompatibleProperty($this->_model, 'tagResolver', $this->tagResolver); - $reflection = new \ReflectionClass(\Magento\PageCache\Observer\FlushCacheByTags::class); - $reflectionProperty = $reflection->getProperty('fullPageCache'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->_model, $this->fullPageCacheMock); } /** @@ -56,28 +71,28 @@ protected function setUp() */ public function testExecute($cacheState) { - $this->_configMock->expects($this->any())->method('isEnabled')->will($this->returnValue($cacheState)); - $observerObject = $this->createMock(\Magento\Framework\Event\Observer::class); - $observedObject = $this->createMock(\Magento\Store\Model\Store::class); + $this->configMock->method('isEnabled')->willReturn($cacheState); + $observerObject = $this->createMock(Observer::class); + $observedObject = $this->createMock(Store::class); if ($cacheState) { $tags = ['cache_1', 'cache_group']; $expectedTags = ['cache_1', 'cache_group']; - $eventMock = $this->createPartialMock(\Magento\Framework\Event::class, ['getObject']); - $eventMock->expects($this->once())->method('getObject')->will($this->returnValue($observedObject)); - $observerObject->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); - $this->_configMock->expects($this->once()) + $eventMock = $this->createPartialMock(Event::class, ['getObject']); + $eventMock->expects($this->once())->method('getObject')->willReturn($observedObject); + $observerObject->expects($this->once())->method('getEvent')->willReturn($eventMock); + $this->configMock->expects($this->once()) ->method('getType') - ->willReturn(\Magento\PageCache\Model\Config::BUILT_IN); - $this->tagResolver->expects($this->once())->method('getTags')->will($this->returnValue($tags)); + ->willReturn(Config::BUILT_IN); + $this->tagResolverMock->expects($this->once())->method('getTags')->willReturn($tags); $this->fullPageCacheMock->expects($this->once()) ->method('clean') ->with(\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $this->equalTo($expectedTags)); } - $result = $this->_model->execute($observerObject); + $result = $this->model->execute($observerObject); $this->assertNull($result); } @@ -92,28 +107,31 @@ public function flushCacheByTagsDataProvider() ]; } + /** + * Test case for cache invalidation with empty tags + */ public function testExecuteWithEmptyTags() { - $this->_configMock->expects($this->any())->method('isEnabled')->will($this->returnValue(true)); - $observerObject = $this->createMock(\Magento\Framework\Event\Observer::class); - $observedObject = $this->createMock(\Magento\Store\Model\Store::class); + $this->configMock->method('isEnabled')->willReturn(true); + $observerObject = $this->createMock(Observer::class); + $observedObject = $this->createMock(Store::class); $tags = []; - $eventMock = $this->createPartialMock(\Magento\Framework\Event::class, ['getObject']); - $eventMock->expects($this->once())->method('getObject')->will($this->returnValue($observedObject)); - $observerObject->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); - $this->_configMock->expects( + $eventMock = $this->createPartialMock(Event::class, ['getObject']); + $eventMock->expects($this->once())->method('getObject')->willReturn($observedObject); + $observerObject->expects($this->once())->method('getEvent')->willReturn($eventMock); + $this->configMock->expects( $this->once() )->method( 'getType' - )->will( - $this->returnValue(\Magento\PageCache\Model\Config::BUILT_IN) + )->willReturn( + Config::BUILT_IN ); - $this->tagResolver->expects($this->once())->method('getTags')->will($this->returnValue($tags)); + $this->tagResolverMock->expects($this->once())->method('getTags')->willReturn($tags); $this->fullPageCacheMock->expects($this->never())->method('clean'); - $this->_model->execute($observerObject); + $this->model->execute($observerObject); } } diff --git a/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php index f4b05df2e8a20..5b1ee10395a96 100644 --- a/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php +++ b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php @@ -9,7 +9,7 @@ use Magento\Sales\Api\Data\OrderAddressInterface; /** - * Class AddressAdapter + * @inheritdoc */ class AddressAdapter implements AddressAdapterInterface { @@ -54,7 +54,7 @@ public function getCountryId() public function getStreetLine1() { $street = $this->address->getStreet(); - return isset($street[0]) ? $street[0]: ''; + return $street[0] ?? ''; } /** @@ -65,7 +65,7 @@ public function getStreetLine1() public function getStreetLine2() { $street = $this->address->getStreet(); - return isset($street[1]) ? $street[1]: ''; + return $street[1] ?? ''; } /** diff --git a/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php index 3c8d5899a1083..57805cee16d30 100644 --- a/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php +++ b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php @@ -9,7 +9,7 @@ use Magento\Quote\Api\Data\AddressInterface; /** - * Class AddressAdapter + * @inheritdoc */ class AddressAdapter implements AddressAdapterInterface { @@ -54,7 +54,7 @@ public function getCountryId() public function getStreetLine1() { $street = $this->address->getStreet(); - return isset($street[0]) ? $street[0]: ''; + return $street[0] ?? ''; } /** @@ -65,7 +65,7 @@ public function getStreetLine1() public function getStreetLine2() { $street = $this->address->getStreet(); - return isset($street[1]) ? $street[1]: ''; + return $street[1] ?? ''; } /** diff --git a/app/code/Magento/Payment/Model/Info.php b/app/code/Magento/Payment/Model/Info.php index 3ca9b072e8321..79a26ef4ed45f 100644 --- a/app/code/Magento/Payment/Model/Info.php +++ b/app/code/Magento/Payment/Model/Info.php @@ -177,7 +177,7 @@ public function getAdditionalInformation($key = null) if (null === $key) { return $this->_additionalInformation; } - return isset($this->_additionalInformation[$key]) ? $this->_additionalInformation[$key] : null; + return $this->_additionalInformation[$key] ?? null; } /** diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php index 6c7ef372a8854..dba48efaae837 100644 --- a/app/code/Magento/Payment/Model/Method/Adapter.php +++ b/app/code/Magento/Payment/Model/Method/Adapter.php @@ -17,6 +17,7 @@ use Magento\Payment\Gateway\Validator\ValidatorPoolInterface; use Magento\Payment\Model\InfoInterface; use Magento\Payment\Model\MethodInterface; +use Magento\Payment\Model\SaleOperationInterface; use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Quote\Api\Data\CartInterface; use Psr\Log\LoggerInterface; @@ -30,7 +31,7 @@ * @api Use this class as a base for virtual types declaration * @since 100.0.2 */ -class Adapter implements MethodInterface +class Adapter implements MethodInterface, SaleOperationInterface { /** * @var ValueHandlerPoolInterface @@ -296,6 +297,7 @@ public function isAvailable(CartInterface $quote = null) $checkResult->setData('is_available', $result->isValid()); } + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (\Exception $e) { // pass } @@ -366,7 +368,7 @@ private function canPerformCommand($commandCode) * Unifies configured value handling logic * * @param string $field - * @param null $storeId + * @param int|null $storeId * @return mixed */ private function getConfiguredValue($field, $storeId = null) @@ -663,4 +665,23 @@ public function getConfigPaymentAction() { return $this->getConfiguredValue('payment_action'); } + + /** + * @inheritdoc + */ + public function canSale(): bool + { + return $this->canPerformCommand('sale'); + } + + /** + * @inheritdoc + */ + public function sale(InfoInterface $payment, float $amount) + { + $this->executeCommand( + 'sale', + ['payment' => $payment, 'amount' => $amount] + ); + } } diff --git a/app/code/Magento/Payment/Model/SaleOperationInterface.php b/app/code/Magento/Payment/Model/SaleOperationInterface.php new file mode 100644 index 0000000000000..384913a75ae26 --- /dev/null +++ b/app/code/Magento/Payment/Model/SaleOperationInterface.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Payment\Model; + +/** + * Responsible for support of `sale` payment operation via Magento payment provider gateway. + * + * @api + */ +interface SaleOperationInterface +{ + /** + * Checks `sale` payment operation availability. + * + * @return bool + */ + public function canSale(): bool; + + /** + * Executes `sale` payment operation. + * + * @param InfoInterface $payment + * @param float $amount + * @return void + */ + public function sale(InfoInterface $payment, float $amount); +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php index dc9a51b30cfea..72c35a192119f 100644 --- a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php @@ -5,46 +5,62 @@ */ namespace Magento\Payment\Test\Unit\Gateway\Data; -use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Model\InfoInterface; +use PHPUnit\Framework\MockObject\MockObject; /** - * Class PaymentDataObjectTest + * Tests for PaymentDataObject */ class PaymentDataObjectTest extends \PHPUnit\Framework\TestCase { - /** @var PaymentDataObject */ + /** + * @var PaymentDataObject + */ protected $model; /** - * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject + * @var OrderAdapterInterface|MockObject */ protected $orderMock; /** - * @var InfoInterface|\PHPUnit_Framework_MockObject_MockObject + * @var InfoInterface|\MockObject */ protected $paymentMock; + /** + * @inheritdoc + */ protected function setUp() { - $this->orderMock = $this->getMockBuilder(\Magento\Payment\Gateway\Data\OrderAdapterInterface::class) + $this->orderMock = $this->getMockBuilder(OrderAdapterInterface::class) ->getMockForAbstractClass(); - $this->paymentMock = $this->getMockBuilder(\Magento\Payment\Model\InfoInterface::class) + $this->paymentMock = $this->getMockBuilder(InfoInterface::class) ->getMockForAbstractClass(); $this->model = new PaymentDataObject($this->orderMock, $this->paymentMock); } - public function testGetOrder() + /** + * Verify can get order + * + * @return void + */ + public function testGetOrder(): void { - $this->assertSame($this->orderMock, $this->model->getOrder()) ; + $this->assertSame($this->orderMock, $this->model->getOrder()); } - public function testGetPayment() + /** + * Verify can get payment + * + * @return void + */ + public function testGetPayment(): void { - $this->assertSame($this->paymentMock, $this->model->getPayment()) ; + $this->assertSame($this->paymentMock, $this->model->getPayment()); } } diff --git a/app/code/Magento/Paypal/Model/AbstractIpn.php b/app/code/Magento/Paypal/Model/AbstractIpn.php index 14d8163fd3bb3..f3f8909ecbd97 100644 --- a/app/code/Magento/Paypal/Model/AbstractIpn.php +++ b/app/code/Magento/Paypal/Model/AbstractIpn.php @@ -8,6 +8,9 @@ use Magento\Framework\Exception\RemoteServiceUnavailableException; +/** + * Abstract Ipn class for paypal + */ class AbstractIpn { /** @@ -39,6 +42,11 @@ class AbstractIpn */ protected $_curlFactory; + /** + * @var \Psr\Log\LoggerInterface + */ + private $logger; + /** * @param \Magento\Paypal\Model\ConfigFactory $configFactory * @param \Psr\Log\LoggerInterface $logger @@ -68,7 +76,7 @@ public function getRequestData($key = null) if (null === $key) { return $this->_ipnRequest; } - return isset($this->_ipnRequest[$key]) ? $this->_ipnRequest[$key] : null; + return $this->_ipnRequest[$key] ?? null; } /** @@ -113,6 +121,7 @@ protected function _postBack() if ($response != 'VERIFIED') { $this->_addDebugData('postback', $postbackQuery); $this->_addDebugData('postback_result', $postbackResult); + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('PayPal IPN postback failure. See system.log for details.'); } } @@ -171,6 +180,8 @@ protected function _debug() } /** + * Adding debug data + * * @param string $key * @param array|string $value * @return $this diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index e197218752bf5..6f6728ebfa47f 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -823,7 +823,7 @@ public function getCountryMethods($countryCode = null) if ($countryCode === null) { return $countryMethods; } - return isset($countryMethods[$countryCode]) ? $countryMethods[$countryCode] : $countryMethods['other']; + return $countryMethods[$countryCode] ?? $countryMethods['other']; } /** @@ -1330,6 +1330,7 @@ public function getPayflowproCcTypesAsOptionArray() * @param string $code * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getIsCreditCardMethod($code) { diff --git a/app/code/Magento/Paypal/Model/Info.php b/app/code/Magento/Paypal/Model/Info.php index bb2e9366e588f..effc72e5780f4 100644 --- a/app/code/Magento/Paypal/Model/Info.php +++ b/app/code/Magento/Paypal/Model/Info.php @@ -334,6 +334,7 @@ public function &exportFromPayment(\Magento\Payment\Model\InfoInterface $payment * * @param \Magento\Payment\Model\InfoInterface $payment * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isPaymentReviewRequired(\Magento\Payment\Model\InfoInterface $payment) { @@ -350,6 +351,7 @@ public static function isPaymentReviewRequired(\Magento\Payment\Model\InfoInterf * * @param \Magento\Payment\Model\InfoInterface $payment * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isFraudReviewAllowed(\Magento\Payment\Model\InfoInterface $payment) { @@ -365,6 +367,7 @@ public static function isFraudReviewAllowed(\Magento\Payment\Model\InfoInterface * * @param \Magento\Payment\Model\InfoInterface $payment * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isPaymentCompleted(\Magento\Payment\Model\InfoInterface $payment) { @@ -377,6 +380,7 @@ public static function isPaymentCompleted(\Magento\Payment\Model\InfoInterface $ * * @param \Magento\Payment\Model\InfoInterface $payment * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isPaymentSuccessful(\Magento\Payment\Model\InfoInterface $payment) { @@ -407,6 +411,7 @@ public static function isPaymentSuccessful(\Magento\Payment\Model\InfoInterface * * @param \Magento\Payment\Model\InfoInterface $payment * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isPaymentFailed(\Magento\Payment\Model\InfoInterface $payment) { @@ -431,6 +436,7 @@ public static function isPaymentFailed(\Magento\Payment\Model\InfoInterface $pay * @link https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables * @link https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_GetTransactionDetails * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * phpcs:disable Magento2.Functions.StaticFunction */ public static function explainPendingReason($code) { @@ -480,6 +486,7 @@ public static function explainPendingReason($code) * @return string * @link https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables * @link https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_GetTransactionDetails + * phpcs:disable Magento2.Functions.StaticFunction */ public static function explainReasonCode($code) { @@ -518,9 +525,7 @@ public static function explainReasonCode($code) 'duplicate' => __('Buyer claims that a possible duplicate payment was made to the merchant.'), 'merchandise' => __('Buyer claims that the received merchandise is unsatisfactory, defective, or damaged.'), ]; - return isset($comments[$code]) - ? $comments[$code] - : __('Unknown reason. Please contact PayPal customer service.'); + return $comments[$code] ?? __('Unknown reason. Please contact PayPal customer service.'); } /** @@ -528,6 +533,7 @@ public static function explainReasonCode($code) * * @param string $code * @return bool; + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isReversalDisputable($code) { @@ -542,7 +548,7 @@ public static function isReversalDisputable($code) 'chargeback_reimbursement' => false, 'chargeback_settlement' => false, ]; - return isset($listOfDisputeCodes[$code]) ? $listOfDisputeCodes[$code] : false; + return $listOfDisputeCodes[$code] ?? false; } /** @@ -611,9 +617,7 @@ protected function _getLabel($key) self::BUYER_TAX_ID_TYPE => __('Buyer\'s Tax ID Type'), ]; } - return isset($this->_labelCodesCache[self::ITEM_LABELS][$key]) - ? $this->_labelCodesCache[self::ITEM_LABELS][$key] - : ''; + return $this->_labelCodesCache[self::ITEM_LABELS][$key] ?? ''; } /** @@ -621,6 +625,7 @@ protected function _getLabel($key) * * @param string $key * @return string + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getCaseTypeLabel($key) { @@ -664,6 +669,7 @@ protected function _getValue($value, $key) case self::BUYER_TAX_ID_TYPE: $outputValue = $this->_getBuyerIdTypeValue($outputValue); // fall-through intentional + // no break default: return $outputValue; } @@ -705,9 +711,7 @@ protected function _getAvsLabel($value) '4' => __('N/A. Address not checked, or acquirer had no response. Service not available'), ]; } - return isset($this->_labelCodesCache[self::PAYPAL_AVS_CODE][$value]) - ? $this->_labelCodesCache[self::PAYPAL_AVS_CODE][$value] - : $value; + return $this->_labelCodesCache[self::PAYPAL_AVS_CODE][$value] ?? $value; } /** @@ -737,9 +741,7 @@ protected function _getCvv2Label($value) '4' => __('N/A. Service not available'), ]; } - return isset($this->_labelCodesCache[self::PAYPAL_CVV_2_MATCH][$value]) - ? $this->_labelCodesCache[self::PAYPAL_CVV_2_MATCH][$value] - : $value; + return $this->_labelCodesCache[self::PAYPAL_CVV_2_MATCH][$value] ?? $value; } /** @@ -756,8 +758,6 @@ protected function _getBuyerIdTypeValue($code) self::BUYER_TAX_ID_TYPE_CPF => __('CPF'), ]; } - return isset($this->_labelCodesCache[self::BUYER_TAX_ID_TYPE][$code]) - ? $this->_labelCodesCache[self::BUYER_TAX_ID_TYPE][$code] - : ''; + return $this->_labelCodesCache[self::BUYER_TAX_ID_TYPE][$code] ?? ''; } } diff --git a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php index 1ec7f4832bcb2..1ef9577105029 100644 --- a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php +++ b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php @@ -11,8 +11,7 @@ use Magento\Sales\Api\Data\OrderPaymentInterface; /** - * Processes AVS codes mapping from PayPal Payflow transaction to - * electronic merchant systems standard. + * Processes AVS codes mapping from PayPal Payflow transaction to electronic merchant systems standard. * * @see https://developer.paypal.com/docs/classic/payflow/integration-guide/#credit-card-transaction-responses * @see http://www.emsecommerce.net/avs_cvv2_response_codes.htm @@ -64,6 +63,6 @@ public function getCode(OrderPaymentInterface $orderPayment) $zipCode = $additionalInfo[Info::PAYPAL_AVSZIP]; $key = $zipCode . $streetCode; - return isset(self::$avsMap[$key]) ? self::$avsMap[$key] : self::$unavailableCode; + return self::$avsMap[$key] ?? self::$unavailableCode; } } diff --git a/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php b/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php index 7aee18440ab05..b226c2193f5c5 100644 --- a/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php +++ b/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php @@ -11,8 +11,7 @@ use Magento\Sales\Api\Data\OrderPaymentInterface; /** - * Processes CVV codes mapping from PayPal Payflow transaction to - * electronic merchant systems standard. + * Processes CVV codes mapping from PayPal Payflow transaction to electronic merchant systems standard. * * @see https://developer.paypal.com/docs/classic/payflow/integration-guide/#credit-card-transaction-responses * @see http://www.emsecommerce.net/avs_cvv2_response_codes.htm @@ -58,6 +57,6 @@ public function getCode(OrderPaymentInterface $orderPayment) $cvv = $additionalInfo[Info::PAYPAL_CVV2MATCH]; - return isset(self::$cvvMap[$cvv]) ? self::$cvvMap[$cvv] : self::$notProvidedCode; + return self::$cvvMap[$cvv] ?? self::$notProvidedCode; } } diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php index 690e09ffd8770..f16b117daf56e 100644 --- a/app/code/Magento/Paypal/Model/Payflowlink.php +++ b/app/code/Magento/Paypal/Model/Payflowlink.php @@ -36,7 +36,7 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro * * @var string */ - protected $_code = \Magento\Paypal\Model\Config::METHOD_PAYFLOWLINK; + protected $_code = Config::METHOD_PAYFLOWLINK; /** * @var string @@ -116,6 +116,11 @@ class Payflowlink extends \Magento\Paypal\Model\Payflowpro */ private $mathRandom; + /** + * @var \Magento\Framework\App\RequestInterface + */ + private $_requestHttp; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -237,8 +242,8 @@ public function isActive($storeId = null) public function initialize($paymentAction, $stateObject) { switch ($paymentAction) { - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH: - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_SALE: + case Config::PAYMENT_ACTION_AUTH: + case Config::PAYMENT_ACTION_SALE: $payment = $this->getInfoInstance(); /** @var Order $order */ $order = $payment->getOrder(); @@ -345,6 +350,7 @@ protected function _processOrder(\Magento\Sales\Model\Order $order) $payment->registerAuthorizationNotification($payment->getBaseAmountAuthorized()); break; case self::TRXTYPE_SALE: + $order->setState(Order::STATE_PROCESSING); $payment->registerCaptureNotification($payment->getBaseAmountAuthorized()); break; default: @@ -500,14 +506,12 @@ public function buildBasicRequest() */ protected function _getTrxTokenType() { - switch ($this->getConfigData('payment_action')) { - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_AUTH: - return self::TRXTYPE_AUTH_ONLY; - case \Magento\Paypal\Model\Config::PAYMENT_ACTION_SALE: - return self::TRXTYPE_SALE; - default: - break; - } + $tokenTypes = [ + Config::PAYMENT_ACTION_AUTH => self::TRXTYPE_AUTH_ONLY, + Config::PAYMENT_ACTION_SALE => self::TRXTYPE_SALE + ]; + + return $tokenTypes[$this->getConfigData('payment_action')] ?? ''; } /** diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 2ba72c4b26bd7..778cd0c728de3 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -556,6 +556,7 @@ public function fetchTransactionInfo(InfoInterface $payment, $transactionId) * * @param string $status * @return bool + * phpcs:disable Magento2.Functions.StaticFunction */ protected static function _isTransactionUnderReview($status) { @@ -980,6 +981,6 @@ private function mapResponseBillToName($billToFirstName, $billToLastName) */ private function mapResponseCreditCardType($ccType) { - return isset($this->ccTypeMap[$ccType]) ? $this->ccTypeMap[$ccType] : $ccType; + return $this->ccTypeMap[$ccType] ?? $ccType; } } diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml index 392014d876e46..b7ebf7dab1c8b 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml @@ -16,6 +16,7 @@ <argument name="productName" type="string"/> </arguments> <click selector="{{PayPalPaymentSection.cartIcon}}" stepKey="openCart"/> + <waitForPageLoad stepKey="waitForCartLoad"/> <seeElement selector="{{PayPalPaymentSection.itemName(productName)}}" stepKey="seeProductName"/> <click selector="{{PayPalPaymentSection.PayPalSubmitBtn}}" stepKey="clickPayPalSubmitBtn"/> <switchToPreviousTab stepKey="switchToPreviousTab"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml index af68a7611cd1d..a1610926b3f36 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml @@ -57,10 +57,10 @@ <element name="email" type="input" selector="//input[contains(@name, 'email') and not(contains(@style, 'display:none'))]"/> <element name="password" type="input" selector="//input[contains(@name, 'password') and not(contains(@style, 'display:none'))]"/> <element name="loginBtn" type="input" selector="button#btnLogin"/> - <element name="reviewUserInfo" type="text" selector="#reviewUserInfo"/> - <element name="cartIcon" type="text" selector="#transactionCart"/> - <element name="itemName" type="text" selector="//span[@title='{{productName}}']" parameterized="true"/> - <element name="PayPalSubmitBtn" type="text" selector="//input[@type='submit']"/> + <element name="reviewUserInfo" type="text" selector="[data-testid=personalized-banner-content]"/> + <element name="cartIcon" type="text" selector="[data-testid='header-show-cart-dropdown-btn']"/> + <element name="itemName" type="text" selector="//p[contains(@class,'CartDropdown_line') and text()='{{productName}}']" parameterized="true"/> + <element name="PayPalSubmitBtn" type="text" selector="#payment-submit-btn"/> <element name="nextButton" type="button" selector="#btnNext"/> <element name="continueButton" type="button" selector=".continueButton"/> </section> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminCheckDefaultValueOfPayPalCustomizeButtonTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminCheckDefaultValueOfPayPalCustomizeButtonTest.xml index 5c10bc9536fcf..3a3ae03d63bf3 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminCheckDefaultValueOfPayPalCustomizeButtonTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminCheckDefaultValueOfPayPalCustomizeButtonTest.xml @@ -22,11 +22,11 @@ </skip> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <actionGroup ref="ConfigPayPalExpressCheckout" stepKey="ConfigPayPalExpressCheckout"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{AdminConfigPaymentMethodsPage.url}}" stepKey="navigateToPaymentConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsConflictResolutionForPayPal.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsConflictResolutionForPayPal.xml index e918a417dcfde..3e1a825861b5e 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsConflictResolutionForPayPal.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsConflictResolutionForPayPal.xml @@ -29,7 +29,7 @@ <magentoCLI command="config:set payment/paypal_express/active 0" stepKey="disablePayPalExpress"/> <magentoCLI command="config:set payment/wps_express/active 0" stepKey="disableWPSExpress"/> <magentoCLI command="config:set payment/hosted_pro/active 0" stepKey="disableHostedProExpress"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Change Merchant Country --> <comment userInput="Change Merchant Country" stepKey="changeMerchantCountryComment"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsSectionState.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsSectionState.xml index 934449dfd136c..ba5e701ceea66 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsSectionState.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminConfigPaymentsSectionState.xml @@ -18,7 +18,7 @@ <testCaseId value="MAGETWO-92043"/> </annotations> <after> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminOnePayPalSolutionsEnabledAtTheSameTimeTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminOnePayPalSolutionsEnabledAtTheSameTimeTest.xml index fd0e74f38287d..ede251ddee647 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminOnePayPalSolutionsEnabledAtTheSameTimeTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminOnePayPalSolutionsEnabledAtTheSameTimeTest.xml @@ -32,7 +32,7 @@ <magentoCLI command="config:set payment/wps_express/active 1" stepKey="enableWPSExpress"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set payment/wps_express/active 0" stepKey="disableWPSExpress"/> <magentoCLI command="config:set payment/paypal_express/active 0" stepKey="disableExpressCheckout"/> </after> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminReportsPayPalSettlementNavigateMenuTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminReportsPayPalSettlementNavigateMenuTest.xml index 03f0167230e9f..d2cdec73551d0 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminReportsPayPalSettlementNavigateMenuTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminReportsPayPalSettlementNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToPayPalSettlementPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/AdminSalesBillingAgreementsNavigateMenuTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/AdminSalesBillingAgreementsNavigateMenuTest.xml index 8c3735fcbd253..2f0013c43fd9e 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/AdminSalesBillingAgreementsNavigateMenuTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/AdminSalesBillingAgreementsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToBillingAgreementsPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml index 78a27106bf406..c8089085b7ee5 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml @@ -28,7 +28,7 @@ </createData> <!-- Create Customer --> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> <!--Config PayPal Express Checkout--> <comment userInput="config PayPal Express Checkout" stepKey="commemtConfigPayPalExpressCheckout"/> <actionGroup ref="ConfigPayPalExpressCheckout" stepKey="ConfigPayPalExpressCheckout"/> @@ -37,7 +37,7 @@ <deleteData stepKey="deleteCategory" createDataKey="createPreReqCategory"/> <deleteData stepKey="deleteProduct" createDataKey="createPreReqProduct"/> <deleteData stepKey="deleteCustomer" createDataKey="createCustomer"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{AdminConfigPaymentMethodsPage.url}}" stepKey="navigateToPaymentConfigurationPage"/> <waitForPageLoad stepKey="waitForPageLoad1"/> diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml index 6adba94e96890..b95d645787fed 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml @@ -16,9 +16,6 @@ <description value="Users are able to place order using Paypal Smart Button"/> <severity value="CRITICAL"/> <testCaseId value="MC-13690"/> - <skip> - <issueId value="DEVOPS-3311"/> - </skip> <group value="paypal"/> </annotations> <before> @@ -40,7 +37,7 @@ <createData entity="PaypalConfig" stepKey="createPaypalExpressConfig"/> <!-- Login --> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> </before> <after> <!-- Cleanup Paypal configurations --> @@ -58,7 +55,7 @@ <deleteData stepKey="deleteCustomer" createDataKey="createCustomer"/> <!-- Logout --> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Login to storefront as previously created customer--> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/CheckShoppingCartBehaviorAfterSessionExpiredTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/CheckShoppingCartBehaviorAfterSessionExpiredTest.xml index 6d35319172823..a2488d564001c 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/CheckShoppingCartBehaviorAfterSessionExpiredTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/CheckShoppingCartBehaviorAfterSessionExpiredTest.xml @@ -31,7 +31,7 @@ <argument name="Customer" value="Simple_US_Customer_NY"/> </actionGroup> <!--Add shipping information--> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddressInfo"> <argument name="Address" value="US_Address_NY"/> </actionGroup> </before> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml index e81694e044f52..eebadbeaa0eec 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/ShippingQuotePersistedForGuestTest.xml @@ -37,7 +37,7 @@ <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Step 1: Login as a Customer with remember me checked--> <actionGroup ref="CustomerLoginOnStorefrontWithRememberMeCheckedActionGroup" stepKey="loginToStorefrontAccountWithRememberMeChecked"> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyShoppingCartPersistenceUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyShoppingCartPersistenceUnderLongTermCookieTest.xml index 35f4fd88f2b09..2aa43e9ef828d 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyShoppingCartPersistenceUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyShoppingCartPersistenceUnderLongTermCookieTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminDeleteCustomerActionGroup" stepKey="deleteJohnDoeCustomer"> <argument name="customerEmail" value="Simple_Customer_Without_Address.email"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Go to storefront and click the Create an Account link--> diff --git a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml index 1b3a996b34e24..1f84200f856d9 100644 --- a/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/Persistent/Test/Mftf/Test/StorefrontVerifyThatInformationAboutViewingComparisonWishlistIsPersistedUnderLongTermCookieTest.xml @@ -60,7 +60,7 @@ <actionGroup ref="AdminDeleteWidgetActionGroup" stepKey="deleteRecentlyViewedProductsWidget"> <argument name="widget" value="RecentlyViewedProductsWidget"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Login to storefront from customer--> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/AdminValidateUrlOnGetVideoInformationTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/AdminValidateUrlOnGetVideoInformationTest.xml index 03fb71ac039a7..183bd64d97678 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Test/AdminValidateUrlOnGetVideoInformationTest.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/AdminValidateUrlOnGetVideoInformationTest.xml @@ -22,7 +22,7 @@ </before> <after> <createData entity="DefaultProductVideoConfig" stepKey="setStoreDefaultConfig"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndexPage"/> <actionGroup ref="GoToCreateProductPageActionGroup" stepKey="goToCreateProduct"> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/YoutubeVideoWindowOnProductPageTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/YoutubeVideoWindowOnProductPageTest.xml index 13d396b4faf45..ee03e811ae579 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Test/YoutubeVideoWindowOnProductPageTest.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/YoutubeVideoWindowOnProductPageTest.xml @@ -85,7 +85,7 @@ <!-- Set product video configuration to default --> <createData entity="DefaultProductVideoConfig" stepKey="setStoreDefaultConfig" before="logout"/> <!--Log Out--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php index 9b5f5c9a126df..86dcd0e4bfc07 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php +++ b/app/code/Magento/Quote/Model/Quote/Item/CartItemPersister.php @@ -6,14 +6,17 @@ namespace Magento\Quote\Model\Quote\Item; -use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\InputException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\LocalizedException; -use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\CartItemInterface; +/** + * Cart item save handler + */ class CartItemPersister { /** @@ -39,6 +42,8 @@ public function __construct( } /** + * Save cart item into cart + * * @param CartInterface $quote * @param CartItemInterface $item * @return CartItemInterface @@ -73,12 +78,13 @@ public function save(CartInterface $quote, CartItemInterface $item) $item = $quote->updateItem($itemId, $buyRequestData); } else { if ($item->getQty() !== $currentItem->getQty()) { + $currentItem->clearMessage(); $currentItem->setQty($qty); /** * Qty validation errors are stored as items message * @see \Magento\CatalogInventory\Model\Quote\Item\QuantityValidator::validate */ - if (!empty($currentItem->getMessage())) { + if (!empty($currentItem->getMessage()) && $currentItem->getHasError()) { throw new LocalizedException(__($currentItem->getMessage())); } } diff --git a/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml index 6e31214b0dddf..020b495dc42a2 100644 --- a/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml +++ b/app/code/Magento/Quote/Test/Mftf/Test/StorefrontGuestCheckoutDisabledProductTest.xml @@ -87,6 +87,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductListing"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Step 1: Add simple product to shopping cart --> <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.name$$)}}" stepKey="amOnSimpleProductPage"/> diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php index cd7a54455a994..279b2c4b4091f 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php @@ -15,7 +15,7 @@ class UpdateQuoteItemsTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\ResourceModel\Quote */ - private $quoteResource ; + private $quoteResource; protected function setUp() { diff --git a/app/code/Magento/Reports/Block/Adminhtml/Product/Lowstock/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Product/Lowstock/Grid.php index 5460dab3a7ff8..a7a79ff05640d 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Product/Lowstock/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Product/Lowstock/Grid.php @@ -3,8 +3,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Reports\Block\Adminhtml\Product\Lowstock; +use Magento\Backend\Block\Template\Context; +use Magento\Backend\Helper\Data; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Framework\Data\Collection as DataCollection; +use Magento\Reports\Model\ResourceModel\Product\Lowstock\Collection; +use Magento\Reports\Model\ResourceModel\Product\Lowstock\CollectionFactory; + /** * Adminhtml low stock products report grid block * @@ -15,20 +24,20 @@ class Grid extends \Magento\Backend\Block\Widget\Grid { /** - * @var \Magento\Reports\Model\ResourceModel\Product\Lowstock\CollectionFactory + * @var CollectionFactory */ protected $_lowstocksFactory; /** - * @param \Magento\Backend\Block\Template\Context $context - * @param \Magento\Backend\Helper\Data $backendHelper - * @param \Magento\Reports\Model\ResourceModel\Product\Lowstock\CollectionFactory $lowstocksFactory + * @param Context $context + * @param Data $backendHelper + * @param CollectionFactory $lowstocksFactory * @param array $data */ public function __construct( - \Magento\Backend\Block\Template\Context $context, - \Magento\Backend\Helper\Data $backendHelper, - \Magento\Reports\Model\ResourceModel\Product\Lowstock\CollectionFactory $lowstocksFactory, + Context $context, + Data $backendHelper, + CollectionFactory $lowstocksFactory, array $data = [] ) { $this->_lowstocksFactory = $lowstocksFactory; @@ -36,6 +45,8 @@ public function __construct( } /** + * @inheritDoc + * * @return \Magento\Backend\Block\Widget\Grid */ protected function _prepareCollection() @@ -56,7 +67,7 @@ protected function _prepareCollection() $storeId = null; } - /** @var $collection \Magento\Reports\Model\ResourceModel\Product\Lowstock\Collection */ + /** @var $collection Collection */ $collection = $this->_lowstocksFactory->create()->addAttributeToSelect( '*' )->filterByIsQtyProductTypes()->joinInventoryItem( @@ -67,7 +78,10 @@ protected function _prepareCollection() $storeId )->setOrder( 'qty', - \Magento\Framework\Data\Collection::SORT_ORDER_ASC + DataCollection::SORT_ORDER_ASC + )->addAttributeToFilter( + 'status', + Status::STATUS_ENABLED ); if ($storeId) { diff --git a/app/code/Magento/Reports/Model/ResourceModel/Order/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Order/Collection.php index d89a118bff94b..0a74c23fad991 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Order/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Order/Collection.php @@ -461,6 +461,7 @@ public function getDateRange($range, $customStart, $customEnd, $returnObjects = $startMonth = isset($startMonthDay[0]) ? (int)$startMonthDay[0] : 1; $startDay = isset($startMonthDay[1]) ? (int)$startMonthDay[1] : 1; $dateStart->setDate($dateStart->format('Y'), $startMonth, $startDay); + $dateStart->modify('-1 year'); if ($range == '2y') { $dateStart->modify('-1 year'); } diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php index 35a14e09e314f..bca9b8662715a 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php @@ -84,7 +84,7 @@ public function addOrderedQty($from = '', $to = '') )->columns( 'SUM(order_items.qty_ordered) as ordered_qty' )->group( - 'order_items.product_id' + 'order_items.sku' ); return $this; } diff --git a/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php index 02eae4d75d2a7..f37bd6c6a7bd2 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php @@ -11,8 +11,13 @@ */ namespace Magento\Reports\Model\ResourceModel\Review\Customer; +use Magento\Framework\DB\Select; + /** + * Report Customer Review collection + * * @api + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ class Collection extends \Magento\Review\Model\ResourceModel\Review\Collection @@ -104,38 +109,49 @@ protected function _joinCustomers() } /** - * {@inheritdoc} + * @inheritdoc * * Additional processing of 'customer_name' field is required, as it is a concat field, which can not be aliased. * @see _joinCustomers */ public function addFieldToFilter($field, $condition = null) { + if ($field === 'review_cnt') { + $conditionSql = $this->_getConditionSql($field, $condition); + $this->getSelect()->having($conditionSql, null, Select::TYPE_CONDITION); + } + if ($field === 'customer_name') { $field = $this->getConnection()->getConcatSql(['customer.firstname', 'customer.lastname'], ' '); } - return parent::addFieldToFilter($field, $condition); + return ($field === 'review_cnt') ? $this : parent::addFieldToFilter($field, $condition); } /** * Get select count sql * - * @return string + * @return \Magento\Framework\DB\Select + * @throws \Zend_Db_Select_Exception */ public function getSelectCountSql() { $countSelect = clone $this->getSelect(); + $havingClauses = $countSelect->getPart(Select::HAVING); + $whereClauses = $countSelect->getPart(Select::WHERE); $countSelect->reset(\Magento\Framework\DB\Select::ORDER); - $countSelect->reset(\Magento\Framework\DB\Select::GROUP); - $countSelect->reset(\Magento\Framework\DB\Select::HAVING); $countSelect->reset(\Magento\Framework\DB\Select::LIMIT_COUNT); $countSelect->reset(\Magento\Framework\DB\Select::LIMIT_OFFSET); - $countSelect->reset(\Magento\Framework\DB\Select::COLUMNS); - $countSelect->reset(\Magento\Framework\DB\Select::WHERE); - - $countSelect->columns(new \Zend_Db_Expr('COUNT(DISTINCT detail.customer_id)')); - - return $countSelect; + if (empty($whereClauses)) { + $countSelect->reset(\Magento\Framework\DB\Select::WHERE); + } + if (empty($havingClauses)) { + $countSelect->reset(\Magento\Framework\DB\Select::HAVING); + $countSelect->columns(new \Zend_Db_Expr('COUNT(DISTINCT detail.customer_id)')); + } + $aggregateSelect = clone $countSelect; + $aggregateSelect->reset(); + $aggregateSelect->from($countSelect, 'COUNT(*)'); + return $aggregateSelect; } } diff --git a/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php index 5343fbc4f6c7b..6f7738a8273bb 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Review/Product/Collection.php @@ -11,7 +11,11 @@ */ namespace Magento\Reports\Model\ResourceModel\Review\Product; +use Magento\Framework\DB\Select; + /** + * Review collection class + * * @api * @since 100.0.2 */ @@ -51,7 +55,7 @@ protected function _joinReview() 'e.entity_id = r.entity_pk_value', [ 'review_cnt' => new \Zend_Db_Expr(sprintf('(%s)', $subSelect)), - 'created_at' => 'MAX(r.created_at)' + 'last_review' => 'MAX(r.created_at)' ] )->group( 'e.entity_id' @@ -87,7 +91,7 @@ protected function _joinReview() */ public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC) { - if (in_array($attribute, ['review_cnt', 'created_at', 'avg_rating', 'avg_rating_approved'])) { + if (in_array($attribute, ['review_cnt', 'last_review', 'avg_rating', 'avg_rating_approved'])) { $this->getSelect()->order($attribute . ' ' . $dir); return $this; } @@ -95,25 +99,50 @@ public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC) return parent::addAttributeToSort($attribute, $dir); } + /** + * Add attribute to filter + * + * @param string $attribute + * @param array|null $condition + * @param string $joinType + * @return $this|\Magento\Catalog\Model\ResourceModel\Product\Collection + */ + public function addAttributeToFilter($attribute, $condition = null, $joinType = 'inner') + { + $aggregateFilterArray = ['review_cnt', 'last_review', 'avg_rating', 'avg_rating_approved']; + if (is_string($attribute) && + in_array($attribute, $aggregateFilterArray)) { + $conditionSql = $this->_getConditionSql($attribute, $condition); + $this->getSelect()->having($conditionSql, null, Select::TYPE_CONDITION); + } + return in_array($attribute, $aggregateFilterArray) ? $this : + parent::addAttributeToFilter($attribute, $condition, $joinType); + } + /** * Get select count sql * * @return \Magento\Framework\DB\Select + * @throws \Zend_Db_Select_Exception */ public function getSelectCountSql() { $this->_renderFilters(); - /* @var \Magento\Framework\DB\Select $select */ + /* @var Select $select */ $select = clone $this->getSelect(); - $select->reset(\Magento\Framework\DB\Select::ORDER); - $select->reset(\Magento\Framework\DB\Select::LIMIT_COUNT); - $select->reset(\Magento\Framework\DB\Select::LIMIT_OFFSET); - $select->reset(\Magento\Framework\DB\Select::COLUMNS); - $select->resetJoinLeft(); - $select->columns(new \Zend_Db_Expr('1')); - - /* @var \Magento\Framework\DB\Select $countSelect */ + $havingClauses = $select->getPart(Select::HAVING); + $select->reset(Select::ORDER); + $select->reset(Select::LIMIT_COUNT); + $select->reset(Select::LIMIT_OFFSET); + + if (empty($havingClauses)) { + $select->reset(Select::COLUMNS); + $select->reset(Select::HAVING); + $select->resetJoinLeft(); + $select->columns(new \Zend_Db_Expr('1')); + } + /* @var Select $countSelect */ $countSelect = clone $select; $countSelect->reset(); $countSelect->from($select, "COUNT(*)"); diff --git a/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGenerateProductsOrderedReportActionGroup.xml b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGenerateProductsOrderedReportActionGroup.xml new file mode 100644 index 0000000000000..f6f8e4d93d033 --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGenerateProductsOrderedReportActionGroup.xml @@ -0,0 +1,24 @@ +<?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="AdminGenerateProductsOrderedReportActionGroup"> + <annotations> + <description>Navigate to Reports > Products > Ordered page. Enters the provided Order From/To Dates. Clicks on 'Refresh'.</description> + </annotations> + <arguments> + <argument name="orderFromDate" type="string"/> + <argument name="orderToDate" type="string"/> + </arguments> + + <amOnPage url="{{SoldReportPage.url}}" stepKey="navigateToOrderedProductPage"/> + <fillField selector="{{SoldReportFilterSection.dateFrom}}" userInput="{{orderFromDate}}" stepKey="fillFromDate"/> + <fillField selector="{{SoldReportFilterSection.dateTo}}" userInput="{{orderToDate}}" stepKey="fillToDate"/> + <click selector="{{SoldReportFilterSection.buttonRefresh}}" stepKey="clickRefresh"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminLowStockReportFilterProductActionGroup.xml b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminLowStockReportFilterProductActionGroup.xml new file mode 100644 index 0000000000000..e77502497d83a --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminLowStockReportFilterProductActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AdminLowStockReportFilterProductActionGroup"> + <annotations> + <description>Filter in "Low Stock" report with by product SKU.</description> + </annotations> + <arguments> + <argument name="sku" type="string" defaultValue="{{_defaultProduct.sku}}"/> + </arguments> + + <fillField selector="{{LowStockReportFilterSection.productSku}}" userInput="{{sku}}" stepKey="fillSkuFilterField" /> + <click selector="{{LowStockReportFilterSection.searchButton}}" stepKey="clickSearch"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Reports/Test/Mftf/Page/SoldReportPage.xml b/app/code/Magento/Reports/Test/Mftf/Page/SoldReportPage.xml new file mode 100644 index 0000000000000..6c883c8234b9a --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/Page/SoldReportPage.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="SoldReportPage" url="reports/report_product/sold/" area="admin" module="Reports"> + <section name="SoldReportMainSection"/> + </page> +</pages> diff --git a/app/code/Magento/Reports/Test/Mftf/Section/SoldReportMainSection.xml b/app/code/Magento/Reports/Test/Mftf/Section/SoldReportMainSection.xml new file mode 100644 index 0000000000000..79f00ce217f6d --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/Section/SoldReportMainSection.xml @@ -0,0 +1,17 @@ +<?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="SoldReportFilterSection"> + <element name="dateFrom" type="input" selector="#gridProductsSold_period_date_from"/> + <element name="dateTo" type="input" selector="#gridProductsSold_period_date_to"/> + <element name="buttonRefresh" type="button" selector="//button/span[contains(text(),'Refresh')]" /> + <element name="gridProduct" type="text" selector="#gridProductsSold_table"/> + </section> +</sections> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsAbandonedCartsNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsAbandonedCartsNavigateMenuTest.xml index 342955e0684b3..b044b7a9b1f79 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsAbandonedCartsNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsAbandonedCartsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToAbandonedCartsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsBestsellersNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsBestsellersNavigateMenuTest.xml index 259f2cde2786a..2c78a9568325b 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsBestsellersNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsBestsellersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsBestsellersPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsCouponsNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsCouponsNavigateMenuTest.xml index 321f3078bc63f..ff3372285b211 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsCouponsNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsCouponsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsCouponsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsDownloadsNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsDownloadsNavigateMenuTest.xml index 584c1af6683aa..05ee0a8032fb5 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsDownloadsNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsDownloadsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsDownloadsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsInvoicedNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsInvoicedNavigateMenuTest.xml index 34aec0620cad9..f28ffc700c34a 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsInvoicedNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsInvoicedNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsInvoicedPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockDisableProductTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockDisableProductTest.xml new file mode 100644 index 0000000000000..841ba89b643bf --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockDisableProductTest.xml @@ -0,0 +1,39 @@ +<?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="AdminReportsLowStockDisableProductTest"> + <annotations> + <features value="Reports"/> + <group value="reports"/> + <title value="The disabled product doesn't present on 'Low Stock' report."/> + <description value="A product must don't presents on 'Low Stock' report if the product is disabled."/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Created disabled simple product with stock quantity zero --> + <createData entity="SimpleProductDisabledStockQuantityZero" stepKey="createProduct"/> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsLowStockPage"> + <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> + <argument name="submenuUiId" value="{{AdminMenuReportsProductsLowStock.dataUiId}}"/> + </actionGroup> + <actionGroup ref="AdminLowStockReportFilterProductActionGroup" stepKey="assertProductInReport"> + <argument name="sku" value="{{SimpleProductDisabledStockQuantityZero.sku}}"/> + </actionGroup> + + <!-- Verify doesn't present in the report --> + <dontSeeElement selector="{{LowStockProductGridSection.productSku}}" stepKey="assertSelector"/> + </test> +</tests> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockNavigateMenuTest.xml index 5d91d65a3a457..986101a8c0db8 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsLowStockNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsLowStockPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsNewNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsNewNavigateMenuTest.xml index aeb35ba65a380..dd97d092041ca 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsNewNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsNewNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsNewPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderCountNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderCountNavigateMenuTest.xml index 1bfbc654746e6..638cc30279966 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderCountNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderCountNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsOrderCountPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderTotalNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderTotalNavigateMenuTest.xml index 88c94b53f5233..c1c8256e3d331 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderTotalNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderTotalNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsOrderTotalPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedGroupedBySkuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedGroupedBySkuTest.xml new file mode 100644 index 0000000000000..52c0e49ee9291 --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedGroupedBySkuTest.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminReportsOrderedGroupedBySkuTest"> + <annotations> + <title value="Verify grouped by SKU on report"/> + <description value="Verify the list of configurable product grouped by SKU, on report page 'Reports > Products > Ordered'"/> + <group value="reports"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="CreateConfigurableProductActionGroup" stepKey="createConfigurableProduct"> + <argument name="product" value="_defaultProduct"/> + <argument name="category" value="$$createCategory$$"/> + </actionGroup> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + </before> + <after> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> + <argument name="sku" value="{{_defaultProduct.sku}}"/> + </actionGroup> + <actionGroup ref="DeleteProductAttributeByLabelActionGroup" stepKey="deleteAttributeSet"> + <argument name="ProductAttribute" value="colorProductAttribute"/> + </actionGroup> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Add first configurable product to order--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToFirstOrderWithExistingCustomer"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + <actionGroup ref="AddConfigurableProductToOrderActionGroup" stepKey="addFirstConfigurableProductToOrder"> + <argument name="product" value="_defaultProduct"/> + <argument name="attribute" value="colorProductAttribute"/> + <argument name="option" value="colorProductAttribute1"/> + </actionGroup> + <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitFirstOrder"/> + + <!--Add second configurable product to order--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToSecondOrderWithExistingCustomer"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + <actionGroup ref="AddConfigurableProductToOrderActionGroup" stepKey="addSecondConfigurableProductToOrder"> + <argument name="product" value="_defaultProduct"/> + <argument name="attribute" value="colorProductAttribute"/> + <argument name="option" value="colorProductAttribute2"/> + </actionGroup> + <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="submitSecondOrder"/> + + <!-- Get date --> + <generateDate stepKey="generateStartDate" date="-1 minute" format="m/d/Y"/> + <generateDate stepKey="generateEndDate" date="+1 minute" format="m/d/Y"/> + <actionGroup ref="AdminGenerateProductsOrderedReportActionGroup" stepKey="generateReport"> + <argument name="orderFromDate" value="$generateStartDate"/> + <argument name="orderToDate" value="$generateEndDate" /> + </actionGroup> + + <!-- Verify data --> + <grabTextFrom selector="{{SoldReportFilterSection.gridProduct}}" stepKey="grabData"/> + <assertContains stepKey="assertFirst"> + <actualResult type="string">{$grabData}</actualResult> + <expectedResult type="string">{{_defaultProduct.sku}}-{{colorProductAttribute1.name}}</expectedResult> + </assertContains> + <assertContains stepKey="assertSecond"> + <actualResult type="string">{$grabData}</actualResult> + <expectedResult type="string">{{_defaultProduct.sku}}-{{colorProductAttribute2.name}}</expectedResult> + </assertContains> + </test> +</tests> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedNavigateMenuTest.xml index e81239539a5b5..9053fb35150b6 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsOrderedPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrdersNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrdersNavigateMenuTest.xml index 13fc8e7353139..77fd6c46196af 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrdersNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrdersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsOrdersPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsProductsInCartNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsProductsInCartNavigateMenuTest.xml index 03877f8e58ecc..00b93b0a93180 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsProductsInCartNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsProductsInCartNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsProductsInCartPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsRefreshStatisticsNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsRefreshStatisticsNavigateMenuTest.xml index d05fc091357df..94290b918969d 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsRefreshStatisticsNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsRefreshStatisticsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsRefreshStatisticsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsTaxNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsTaxNavigateMenuTest.xml index 11a065c933a3b..6b34f51c39d88 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsTaxNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsTaxNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsTaxPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsViewsNavigateMenuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsViewsNavigateMenuTest.xml index 9154b96c71e38..ff259cc5870ff 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsViewsNavigateMenuTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsViewsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsViewsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml index 324b56757c516..0435ab6b7be49 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml @@ -37,7 +37,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/Sold/Collection/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/Sold/Collection/CollectionTest.php index c4be25843b128..6e2fd8d847063 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/Sold/Collection/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Product/Sold/Collection/CollectionTest.php @@ -3,52 +3,154 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Reports\Test\Unit\Model\ResourceModel\Product\Sold\Collection; +use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Reports\Model\ResourceModel\Product\Sold\Collection; +use Magento\Sales\Model\Order; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** + * Verify data collection class. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class CollectionTest extends \PHPUnit\Framework\TestCase +class CollectionTest extends TestCase { /** - * @var ObjectManager + * @var AdapterInterface|MockObject */ - protected $objectManager; + protected $adapterMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Select|MockObject */ protected $selectMock; + /** + * @var Collection; + */ + protected $collection; + + /** + * @inheritDoc + */ protected function setUp() { - $this->objectManager = new ObjectManager($this); $this->selectMock = $this->createMock(Select::class); - } - - public function testGetSelectCountSql() - { - /** @var $collection \PHPUnit_Framework_MockObject_MockObject */ - $collection = $this->getMockBuilder(Collection::class) - ->setMethods(['getSelect']) + $this->adapterMock = $this->createMock(AdapterInterface::class); + $this->collection = $this->getMockBuilder(Collection::class) + ->setMethods([ + 'getSelect', + 'getConnection', + 'getTable' + ]) ->disableOriginalConstructor() ->getMock(); + } - $collection->expects($this->atLeastOnce())->method('getSelect')->willReturn($this->selectMock); - - $this->selectMock->expects($this->atLeastOnce())->method('reset')->willReturnSelf(); - $this->selectMock->expects($this->exactly(2))->method('columns')->willReturnSelf(); + /** + * Verify get select count sql. + * + * @return void + */ + public function testGetSelectCountSql(): void + { + $this->collection->expects($this->atLeastOnce()) + ->method('getSelect') + ->willReturn($this->selectMock); + $this->selectMock->expects($this->atLeastOnce()) + ->method('reset') + ->willReturnSelf(); + $this->selectMock->expects($this->exactly(2)) + ->method('columns') + ->willReturnSelf(); + $this->selectMock->expects($this->at(6)) + ->method('columns') + ->with('COUNT(DISTINCT main_table.entity_id)'); + $this->selectMock->expects($this->at(7)) + ->method('reset') + ->with(Select::COLUMNS); + $this->selectMock->expects($this->at(8)) + ->method('columns') + ->with('COUNT(DISTINCT order_items.item_id)'); - $this->selectMock->expects($this->at(6))->method('columns')->with('COUNT(DISTINCT main_table.entity_id)'); + $this->assertEquals($this->selectMock, $this->collection->getSelectCountSql()); + } - $this->selectMock->expects($this->at(7))->method('reset')->with(Select::COLUMNS); - $this->selectMock->expects($this->at(8))->method('columns')->with('COUNT(DISTINCT order_items.item_id)'); + /** + * Verify add ordered qty. + * + * @return void + */ + public function testAddOrderedQty(): void + { + $this->collection->expects($this->once()) + ->method('getConnection') + ->willReturn($this->adapterMock); + $this->adapterMock->expects($this->once()) + ->method('quoteIdentifier') + ->with('order') + ->willReturn('sales_order'); + $this->adapterMock->expects($this->once()) + ->method('quoteInto') + ->with('sales_order.state <> ?', Order::STATE_CANCELED) + ->willReturn(''); + $this->collection->expects($this->atLeastOnce()) + ->method('getSelect') + ->willReturn($this->selectMock); + $this->collection->expects($this->exactly(2)) + ->method('getTable') + ->withConsecutive( + ['sales_order_item'], + ['sales_order'] + )->willReturnOnConsecutiveCalls( + 'sales_order_item', + 'sales_order' + ); + $this->selectMock->expects($this->atLeastOnce()) + ->method('reset') + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('from') + ->with( + [ 'order_items' => 'sales_order_item'], + [ + 'ordered_qty' => 'order_items.qty_ordered', + 'order_items_name' => 'order_items.name', + 'order_items_sku' => 'order_items.sku' + ] + ) + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('joinInner') + ->with( + ['order' => 'sales_order'], + 'sales_order.entity_id = order_items.order_id AND ', + [] + ) + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('where') + ->with('order_items.parent_item_id IS NULL') + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('having') + ->with('order_items.qty_ordered > ?', 0) + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('columns') + ->with('SUM(order_items.qty_ordered) as ordered_qty') + ->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce()) + ->method('group') + ->with('order_items.sku') + ->willReturnSelf(); - $this->assertEquals($this->selectMock, $collection->getSelectCountSql()); + $this->assertEquals($this->collection, $this->collection->addOrderedQty()); } } diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Customer/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Customer/CollectionTest.php new file mode 100644 index 0000000000000..2d22d0b4aa4d3 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Customer/CollectionTest.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Reports\Test\Unit\Model\ResourceModel\Review\Customer; + +use Magento\Framework\DB\Select; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Reports\Model\ResourceModel\Review\Customer\Collection; + +/** + * Review product collection test + */ +class CollectionTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $selectMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $collectionMock; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->selectMock = $this->createMock(Select::class); + $this->collectionMock = $this->getMockBuilder(Collection::class) + ->setMethods(['getSelect']) + ->disableOriginalConstructor() + ->getMock(); + $this->collectionMock->expects($this->atLeastOnce())->method('getSelect')->willReturn($this->selectMock); + } + + public function testGetSelectCountSqlWithoutHavingClauses() + { + $havingClauses = []; + $whereClauses = []; + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($havingClauses); + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($whereClauses); + $this->selectMock->expects($this->at(2))->method('reset')->with(Select::ORDER); + $this->selectMock->expects($this->at(3))->method('reset')->with(Select::LIMIT_COUNT); + $this->selectMock->expects($this->at(4))->method('reset')->with(Select::LIMIT_OFFSET); + $this->selectMock->expects($this->at(5))->method('reset')->with(Select::WHERE); + $this->selectMock->expects($this->at(6))->method('reset')->with(Select::HAVING); + $this->selectMock->expects($this->atLeastOnce())->method('columns') + ->with(new \Zend_Db_Expr('COUNT(DISTINCT detail.customer_id)'))->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('reset')->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('from')->willReturnSelf(); + + $this->assertEquals($this->selectMock, $this->collectionMock->getSelectCountSql()); + } + + public function testGetSelectCountSqlWithHavingClauses() + { + $havingClauses = [ + 'clause-1' => '(review_cnt LIKE %4%)', + 'clause-2' => '(avg_rating LIKE %55.00%)' + ]; + $whereClauses = [ + 'customer name LIKE %test%' + ]; + + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($havingClauses); + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($whereClauses); + $this->selectMock->expects($this->at(2))->method('reset')->with(Select::ORDER); + $this->selectMock->expects($this->at(3))->method('reset')->with(Select::LIMIT_COUNT); + $this->selectMock->expects($this->at(4))->method('reset')->with(Select::LIMIT_OFFSET); + $this->selectMock->expects($this->atLeastOnce())->method('reset')->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('from')->willReturnSelf(); + + $this->assertEquals($this->selectMock, $this->collectionMock->getSelectCountSql()); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php new file mode 100644 index 0000000000000..d2c22d972e24a --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Reports\Test\Unit\Model\ResourceModel\Review\Product; + +use Magento\Framework\DB\Select; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Reports\Model\ResourceModel\Review\Product\Collection; + +/** + * Review product collection test + */ +class CollectionTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $selectMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $collectionMock; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->selectMock = $this->createMock(Select::class); + $this->collectionMock = $this->getMockBuilder(Collection::class) + ->setMethods(['getSelect']) + ->disableOriginalConstructor() + ->getMock(); + $this->collectionMock->expects($this->atLeastOnce())->method('getSelect')->willReturn($this->selectMock); + } + + public function testGetSelectCountSqlWithoutHavingClauses() + { + $havingClauses = []; + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($havingClauses); + $this->selectMock->expects($this->at(1))->method('reset')->with(Select::ORDER); + $this->selectMock->expects($this->at(2))->method('reset')->with(Select::LIMIT_COUNT); + $this->selectMock->expects($this->at(3))->method('reset')->with(Select::LIMIT_OFFSET); + $this->selectMock->expects($this->atLeastOnce())->method('columns') + ->with(new \Zend_Db_Expr('1'))->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('resetJoinLeft')->willReturnSelf(); + + $this->selectMock->expects($this->at(4))->method('reset')->with(Select::COLUMNS); + $this->selectMock->expects($this->at(5))->method('reset')->with(Select::HAVING); + $this->selectMock->expects($this->atLeastOnce())->method('reset')->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('from')->willReturnSelf(); + + $this->assertEquals($this->selectMock, $this->collectionMock->getSelectCountSql()); + } + + public function testGetSelectCountSqlWithHavingClauses() + { + $havingClauses = [ + 'clause-1' => '(review_cnt LIKE %4%)', + 'clause-2' => '(avg_rating LIKE %55.00%)' + ]; + + $this->selectMock->expects($this->atLeastOnce())->method('getPart')->willReturn($havingClauses); + $this->selectMock->expects($this->at(1))->method('reset')->with(Select::ORDER); + $this->selectMock->expects($this->at(2))->method('reset')->with(Select::LIMIT_COUNT); + $this->selectMock->expects($this->at(3))->method('reset')->with(Select::LIMIT_OFFSET); + $this->selectMock->expects($this->atLeastOnce())->method('reset')->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('from')->willReturnSelf(); + + $this->assertEquals($this->selectMock, $this->collectionMock->getSelectCountSql()); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Observer/CatalogProductCompareClearObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/CatalogProductCompareClearObserverTest.php new file mode 100644 index 0000000000000..018ab943ef9ed --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/CatalogProductCompareClearObserverTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Reports\Test\Unit\Observer; + +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Reports\Model\Event; +use Magento\Reports\Model\Product\Index\Compared; +use Magento\Reports\Model\Product\Index\ComparedFactory; +use Magento\Reports\Model\ReportStatus; +use Magento\Reports\Observer\CatalogProductCompareClearObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for Magento\Reports\Test\Unit\Observer\CatalogProductCompareClearObserver + */ +class CatalogProductCompareClearObserverTest extends TestCase +{ + /** + * Testable Object + * + * @var CatalogProductCompareClearObserver + */ + private $observer; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var ReportStatus|MockObject + */ + private $reportStatusMock; + + /** + * @var ComparedFactory|MockObject + */ + private $productCompFactoryMock; + + /** + * @var Compared|MockObject + */ + private $productCompModelMock; + + /** + * @var Event|MockObject + */ + private $reportEventMock; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + + $this->reportStatusMock = $this->getMockBuilder(ReportStatus::class) + ->disableOriginalConstructor() + ->setMethods(['isReportEnabled']) + ->getMock(); + + $this->reportEventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->productCompFactoryMock = $this->getMockBuilder(ComparedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->productCompModelMock = $this->getMockBuilder(Compared::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->observer = $this->objectManager->getObject( + CatalogProductCompareClearObserver::class, + [ + 'reportStatus' => $this->reportStatusMock, + 'productCompFactory' => $this->productCompFactoryMock + ] + ); + } + + /** + * Test for execute(), covers test case for remove all products from compare products + */ + public function testExecuteRemoveProducts(): void + { + $this->reportStatusMock + ->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_VIEW) + ->willReturn(true); + + $this->productCompFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($this->productCompModelMock); + + $this->productCompModelMock + ->expects($this->once()) + ->method('calculate') + ->willReturnSelf(); + + $this->observer->execute($this->observerMock); + } + + /** + * Test for execute(), covers test case for remove all products from compare products with report disabled + */ + public function testExecuteRemoveProductsWithReportDisable(): void + { + $this->reportStatusMock + ->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_VIEW) + ->willReturn(false); + + $this->productCompFactoryMock + ->expects($this->never()) + ->method('create'); + + $this->productCompModelMock + ->expects($this->never()) + ->method('calculate'); + + $this->observer->execute($this->observerMock); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Observer/SendfriendProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/SendfriendProductObserverTest.php new file mode 100644 index 0000000000000..88c30ec5bc236 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/SendfriendProductObserverTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Reports\Test\Unit\Observer; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Reports\Model\Event; +use Magento\Reports\Model\ReportStatus; +use Magento\Reports\Observer\EventSaver; +use Magento\Reports\Observer\SendfriendProductObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Reports\Observer\SendfriendProductObserver + */ +class SendfriendProductObserverTest extends TestCase +{ + /** + * @var Observer|MockObject + */ + private $eventObserverMock; + + /** + * @var EventSaver|MockObject + */ + private $eventSaverMock; + + /** + * @var ReportStatus|MockObject + */ + private $reportStatusMock; + + /** + * @var SendfriendProductObserver + */ + private $observer; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->eventObserverMock = $this->createMock(Observer::class); + $this->eventSaverMock = $this->createMock(EventSaver::class); + $this->reportStatusMock = $this->createMock(ReportStatus::class); + + $this->observer = (new ObjectManagerHelper($this))->getObject( + SendfriendProductObserver::class, + ['eventSaver' => $this->eventSaverMock, 'reportStatus' => $this->reportStatusMock] + ); + } + + /** + * Test case when report is disabled in config. + */ + public function testExecuteWhenReportIsDisabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_SEND) + ->willReturn(false); + + $this->eventSaverMock->expects($this->never())->method('save'); + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when report is enabled in config. + */ + public function testExecuteWhenReportIsEnabled() + { + $eventMock = $this->createPartialMock(Event::class, ['getProduct']); + $eventMock->expects($this->once()) + ->method('getProduct') + ->willReturn($this->createMock(ProductInterface::class)); + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_SEND) + ->willReturn(true); + $this->eventObserverMock->expects($this->once())->method('getEvent')->willReturn($eventMock); + + $this->eventSaverMock->expects($this->once())->method('save'); + $this->observer->execute($this->eventObserverMock); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Observer/WishlistAddProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/WishlistAddProductObserverTest.php new file mode 100644 index 0000000000000..5b282bb60ece2 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/WishlistAddProductObserverTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Reports\Test\Unit\Observer; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Reports\Model\Event; +use Magento\Reports\Model\ReportStatus; +use Magento\Reports\Observer\EventSaver; +use Magento\Reports\Observer\WishlistAddProductObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Reports\Observer\WishlistAddProductObserver + */ +class WishlistAddProductObserverTest extends TestCase +{ + /** + * @var Observer|MockObject + */ + private $eventObserverMock; + + /** + * @var EventSaver|MockObject + */ + private $eventSaverMock; + + /** + * @var ReportStatus|MockObject + */ + private $reportStatusMock; + + /** + * @var WishlistAddProductObserver + */ + private $observer; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->eventObserverMock = $this->createMock(Observer::class); + $this->eventSaverMock = $this->createMock(EventSaver::class); + $this->reportStatusMock = $this->createMock(ReportStatus::class); + + $this->observer = (new ObjectManagerHelper($this))->getObject( + WishlistAddProductObserver::class, + ['eventSaver' => $this->eventSaverMock, 'reportStatus' => $this->reportStatusMock] + ); + } + + /** + * Test case when report is disabled in config. + */ + public function testExecuteWhenReportIsDisabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_TO_WISHLIST) + ->willReturn(false); + $this->eventSaverMock->expects($this->never())->method('save'); + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when report is enabled in config. + */ + public function testExecuteWhenReportIsEnabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_PRODUCT_TO_WISHLIST) + ->willReturn(true); + + $eventMock = $this->createPartialMock(Event::class, ['getProduct']); + $eventMock->expects($this->once()) + ->method('getProduct') + ->willReturn($this->createMock(ProductInterface::class)); + $this->eventObserverMock->expects($this->once())->method('getEvent')->willReturn($eventMock); + + $this->eventSaverMock->expects($this->once())->method('save'); + $this->observer->execute($this->eventObserverMock); + } +} diff --git a/app/code/Magento/Reports/Test/Unit/Observer/WishlistShareObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/WishlistShareObserverTest.php new file mode 100644 index 0000000000000..d432fe013b138 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/WishlistShareObserverTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Reports\Test\Unit\Observer; + +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Reports\Model\Event; +use Magento\Reports\Model\ReportStatus; +use Magento\Reports\Observer\EventSaver; +use Magento\Reports\Observer\WishlistShareObserver; +use Magento\Wishlist\Model\Wishlist; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Reports\Observer\WishlistShareObserver + */ +class WishlistShareObserverTest extends TestCase +{ + /** + * @var Observer|MockObject + */ + private $eventObserverMock; + + /** + * @var EventSaver|MockObject + */ + private $eventSaverMock; + + /** + * @var ReportStatus|MockObject + */ + private $reportStatusMock; + + /** + * @var WishlistShareObserver + */ + private $observer; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->eventObserverMock = $this->createMock(Observer::class); + $this->eventSaverMock = $this->createMock(EventSaver::class); + $this->reportStatusMock = $this->createMock(ReportStatus::class); + + $this->observer = (new ObjectManagerHelper($this))->getObject( + WishlistShareObserver::class, + ['eventSaver' => $this->eventSaverMock, 'reportStatus' => $this->reportStatusMock] + ); + } + + /** + * Test case when report is disabled in config. + */ + public function testExecuteWhenReportIsDisabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_WISHLIST_SHARE) + ->willReturn(false); + $this->eventSaverMock->expects($this->never())->method('save'); + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when report is enabled in config. + */ + public function testExecuteWhenReportIsEnabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(Event::EVENT_WISHLIST_SHARE) + ->willReturn(true); + + $eventMock = $this->createPartialMock(Event::class, ['getWishlist']); + $eventMock->expects($this->once()) + ->method('getWishlist') + ->willReturn($this->createMock(Wishlist::class)); + $this->eventObserverMock->expects($this->once())->method('getEvent')->willReturn($eventMock); + + $this->eventSaverMock->expects($this->once())->method('save'); + $this->observer->execute($this->eventObserverMock); + } +} diff --git a/app/code/Magento/Reports/etc/db_schema_whitelist.json b/app/code/Magento/Reports/etc/db_schema_whitelist.json index 8f55ef4fdbee6..ea65c73ab789b 100644 --- a/app/code/Magento/Reports/etc/db_schema_whitelist.json +++ b/app/code/Magento/Reports/etc/db_schema_whitelist.json @@ -149,4 +149,4 @@ "REPORT_VIEWED_PRD_AGGRED_YEARLY_PRD_ID_SEQUENCE_PRD_SEQUENCE_VAL": true } } -} \ No newline at end of file +} diff --git a/app/code/Magento/Review/Controller/Adminhtml/Product/Pending.php b/app/code/Magento/Review/Controller/Adminhtml/Product/Pending.php index 385b7e12bf32a..6e5e64b25985c 100644 --- a/app/code/Magento/Review/Controller/Adminhtml/Product/Pending.php +++ b/app/code/Magento/Review/Controller/Adminhtml/Product/Pending.php @@ -31,6 +31,7 @@ public function execute() } /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_Review::catalog_reviews_ratings_pending'); $resultPage->getConfig()->getTitle()->prepend(__('Customer Reviews')); $resultPage->getConfig()->getTitle()->prepend(__('Pending Reviews')); $this->coreRegistry->register('usePendingFilter', true); diff --git a/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php b/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php index f18bc2094930a..e7597f7c313e4 100644 --- a/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php +++ b/app/code/Magento/Review/Model/ResourceModel/Review/Summary.php @@ -79,14 +79,14 @@ public function reAggregate($summary) * Append review summary fields to product collection * * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection - * @param string $storeId + * @param int $storeId * @param string $entityCode * @return Summary * @throws \Magento\Framework\Exception\LocalizedException */ public function appendSummaryFieldsToCollection( \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection, - string $storeId, + int $storeId, string $entityCode ) { if (!$productCollection->isLoaded()) { diff --git a/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php b/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php index bb69284b5f0b8..4ee5a5e559fab 100644 --- a/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php +++ b/app/code/Magento/Review/Observer/CatalogProductListCollectionAppendSummaryFieldsObserver.php @@ -53,7 +53,7 @@ public function execute(EventObserver $observer) $productCollection = $observer->getEvent()->getCollection(); $this->sumResourceFactory->create()->appendSummaryFieldsToCollection( $productCollection, - $this->storeManager->getStore()->getId(), + (int)$this->storeManager->getStore()->getId(), \Magento\Review\Model\Review::ENTITY_PRODUCT_CODE ); diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminAssertClassElementRelativeIdActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminAssertClassElementRelativeIdActionGroup.xml new file mode 100644 index 0000000000000..63013ea79b834 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminAssertClassElementRelativeIdActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AdminAssertClassElementRelativeIdActionGroup"> + <arguments> + <argument name="elementId" type="string" defaultValue="{{AdminMenuSection.marketing}}"/> + <argument name="expectClass" type="string" defaultValue="{{AdminMenuUserContentPendingReviews.activeClass}}" /> + </arguments> + + <grabAttributeFrom selector="{{elementId}}" userInput="class" stepKey="grabClass"/> + <assertContains stepKey="assertClass"> + <actualResult type="string">{$grabClass}</actualResult> + <expectedResult type="string">{{expectClass}}</expectedResult> + </assertContains> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Review/Test/Mftf/Data/AdminMenuData.xml b/app/code/Magento/Review/Test/Mftf/Data/AdminMenuData.xml index 89882707f5ebd..faff1e1f42932 100644 --- a/app/code/Magento/Review/Test/Mftf/Data/AdminMenuData.xml +++ b/app/code/Magento/Review/Test/Mftf/Data/AdminMenuData.xml @@ -13,6 +13,12 @@ <data key="title">Reviews</data> <data key="dataUiId">magento-review-catalog-reviews-ratings-reviews-all</data> </entity> + <entity name="AdminMenuUserContentPendingReviews"> + <data key="pageTitle">Pending Reviews</data> + <data key="title">Pending Reviews</data> + <data key="dataUiId">magento-review-catalog-reviews-ratings-pending</data> + <data key="dataActiveClass">_active</data> + </entity> <entity name="AdminMenuReportsReviewsByCustomers"> <data key="pageTitle">Customer Reviews Report</data> <data key="title">By Customers</data> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingPendingReviewsNavigateMenuActiveTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingPendingReviewsNavigateMenuActiveTest.xml new file mode 100644 index 0000000000000..f1bba674ac5eb --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingPendingReviewsNavigateMenuActiveTest.xml @@ -0,0 +1,36 @@ +<?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="AdminMarketingPendingReviewsNavigateMenuActiveTest"> + <annotations> + <features value="Pending Reviews"/> + <stories value="Menu Navigation"/> + <title value="Admin marketing pending reviews navigate menu"/> + <description value="Admin able see navigate head menu Marketing is active, when open page Marketing > Pending Reviews"/> + <group value="menu"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsViewsPage"> + <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> + <argument name="submenuUiId" value="{{AdminMenuUserContentPendingReviews.dataUiId}}"/> + </actionGroup> + <actionGroup ref="AdminAssertPageTitleActionGroup" stepKey="seePageTitle"> + <argument name="title" value="{{AdminMenuUserContentPendingReviews.pageTitle}}"/> + </actionGroup> + <actionGroup ref="AdminAssertClassElementRelativeIdActionGroup" stepKey="assertClass"> + <argument name="elementId" value="{{AdminMenuSection.marketing}}"/> + <argument name="expectClass" value="{{AdminMenuUserContentPendingReviews.dataActiveClass}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingReviewsNavigateMenuTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingReviewsNavigateMenuTest.xml index fade220d22100..5f0bf53012126 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingReviewsNavigateMenuTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminMarketingReviewsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsViewsPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByCustomersNavigateMenuTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByCustomersNavigateMenuTest.xml index 58492424e76f7..bc8b5655ad537 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByCustomersNavigateMenuTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByCustomersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsByCustomersPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByProductsNavigateMenuTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByProductsNavigateMenuTest.xml index e848aa4f22023..cab50343efb54 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByProductsNavigateMenuTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminReportsByProductsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsByProductsPage"> <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminStoresRatingNavigateMenuTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminStoresRatingNavigateMenuTest.xml index 511ed5439dc3d..ad211a2ee0ec8 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminStoresRatingNavigateMenuTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminStoresRatingNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresRatingPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeNoTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeNoTest.xml index 77789dd172bdd..f6e80119610c0 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeNoTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeNoTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateToNewRatingFormActionGroup" stepKey="navigateToNewRatingPage" /> <actionGroup ref="AdminAssertStoreViewRatingTitleWhenSingleStoreModeIsNoActionGroup" stepKey="verifyForm" /> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeYesTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeYesTest.xml index e5368e9192c98..5c4a455dde9ae 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeYesTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminVerifyNewRatingFormSingleStoreModeYesTest.xml @@ -24,7 +24,7 @@ </before> <after> <magentoCLI command="config:set general/single_store_mode/enabled 0" stepKey="enabledSingleStoreMode"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateToNewRatingFormActionGroup" stepKey="navigateToNewRatingPage" /> <actionGroup ref="AdminAssertStoreViewRatingTitleWhenSingleStoreModeIsYesActionGroup" stepKey="verifyForm" /> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml index c981d70938e11..c76c30b47ac51 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{StorefrontProductPage.url($$createProduct.name$$)}}" stepKey="goToProductPage"/> diff --git a/app/code/Magento/Review/Test/Unit/Observer/CatalogProductListCollectionAppendSummaryFieldsObserverTest.php b/app/code/Magento/Review/Test/Unit/Observer/CatalogProductListCollectionAppendSummaryFieldsObserverTest.php index 894463de93227..e67b1c815b28f 100644 --- a/app/code/Magento/Review/Test/Unit/Observer/CatalogProductListCollectionAppendSummaryFieldsObserverTest.php +++ b/app/code/Magento/Review/Test/Unit/Observer/CatalogProductListCollectionAppendSummaryFieldsObserverTest.php @@ -23,7 +23,7 @@ */ class CatalogProductListCollectionAppendSummaryFieldsObserverTest extends TestCase { - private const STORE_ID = '1'; + private const STORE_ID = 1; /** * @var Event|MockObject diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php index 1b275c4d809cb..dd62411ea3454 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Status/NewStatus/Form.php @@ -100,7 +100,7 @@ protected function _addStoresFieldset($model, $form) 'fieldset_html_class' => 'store' ] ); - return ; + return; } $renderer = $this->getLayout()->createBlock( diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 8a760065439d6..598b204a33097 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -858,7 +858,7 @@ public function canEdit() */ public function canReorder() { - return $this->_canReorder(false); + return $this->_canReorder(); } /** diff --git a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php index 4dbc10308f3be..c6b40800d5160 100644 --- a/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php +++ b/app/code/Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php @@ -17,8 +17,10 @@ use Magento\Framework\DataObject; /** - * Class ShipmentSender + * Class for shipment email notification sender * + * @deprecated since this class works only with the concrete model and no data interface + * @see \Magento\Sales\Model\Order\Shipment\Sender\EmailSender * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShipmentSender extends Sender diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index dcf6d86b44cae..3076c6dfd2ba7 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -8,10 +8,12 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\PriceCurrencyInterface; +use Magento\Payment\Model\SaleOperationInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment\Info; +use Magento\Sales\Model\Order\Payment\Operations\SaleOperation; use Magento\Sales\Model\Order\Payment\Transaction; use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface; use Magento\Sales\Api\CreditmemoManagementInterface as CreditmemoManager; @@ -115,6 +117,11 @@ class Payment extends Info implements OrderPaymentInterface */ private $creditmemoManager = null; + /** + * @var SaleOperation + */ + private $saleOperation; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -133,6 +140,7 @@ class Payment extends Info implements OrderPaymentInterface * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @param CreditmemoManager $creditmemoManager + * @param SaleOperation $saleOperation * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -152,7 +160,8 @@ public function __construct( \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], - CreditmemoManager $creditmemoManager = null + CreditmemoManager $creditmemoManager = null, + SaleOperation $saleOperation = null ) { $this->priceCurrency = $priceCurrency; $this->creditmemoFactory = $creditmemoFactory; @@ -162,6 +171,8 @@ public function __construct( $this->orderPaymentProcessor = $paymentProcessor; $this->orderRepository = $orderRepository; $this->creditmemoManager = $creditmemoManager ?: ObjectManager::getInstance()->get(CreditmemoManager::class); + $this->saleOperation = $saleOperation ?: ObjectManager::getInstance()->get(SaleOperation::class); + parent::__construct( $context, $registry, @@ -451,7 +462,11 @@ protected function processAction($action, Order $order) case \Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE_CAPTURE: $this->setAmountAuthorized($totalDue); $this->setBaseAmountAuthorized($baseTotalDue); - $this->capture(null); + if ($this->canSale()) { + $this->saleOperation->execute($this); + } else { + $this->capture(null); + } break; default: break; @@ -2572,4 +2587,16 @@ private function collectTotalAmounts(Order $order, array $keys) return $result; } + + /** + * Check sale operation availability for payment method. + * + * @return bool + */ + private function canSale(): bool + { + $method = $this->getMethodInstance(); + + return $method instanceof SaleOperationInterface && $method->canSale(); + } } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php index 3784ba0504be6..34193f06f7a6a 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php @@ -9,10 +9,45 @@ use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment; -use Magento\Sales\Model\Order\Payment\Transaction; +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; +use Magento\Sales\Model\Order\Payment\State\CommandInterface; +use Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface; +use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface; +/** + * Capture operation implementation. + */ class CaptureOperation extends AbstractOperation { + /** + * @var ProcessInvoiceOperation + */ + private $processInvoiceOperation; + + /** + * @param CommandInterface $stateCommand + * @param BuilderInterface $transactionBuilder + * @param ManagerInterface $transactionManager + * @param EventManagerInterface $eventManager + * @param ProcessInvoiceOperation $processInvoiceOperation + */ + public function __construct( + CommandInterface $stateCommand, + BuilderInterface $transactionBuilder, + ManagerInterface $transactionManager, + EventManagerInterface $eventManager, + ProcessInvoiceOperation $processInvoiceOperation + ) { + $this->processInvoiceOperation = $processInvoiceOperation; + + parent::__construct( + $stateCommand, + $transactionBuilder, + $transactionManager, + $eventManager + ); + } + /** * Captures payment. * @@ -34,81 +69,7 @@ public function capture(OrderPaymentInterface $payment, $invoice) } return $payment; } - $amountToCapture = $payment->formatAmount($invoice->getBaseGrandTotal()); - $order = $payment->getOrder(); - - $payment->setTransactionId( - $this->transactionManager->generateTransactionId( - $payment, - Transaction::TYPE_CAPTURE, - $payment->getAuthorizationTransaction() - ) - ); - - $this->eventManager->dispatch( - 'sales_order_payment_capture', - ['payment' => $payment, 'invoice' => $invoice] - ); - - /** - * Fetch an update about existing transaction. It can determine whether the transaction can be paid - * Capture attempt will happen only when invoice is not yet paid and the transaction can be paid - */ - if ($invoice->getTransactionId()) { - $method = $payment->getMethodInstance(); - $method->setStore( - $order->getStoreId() - ); - if ($method->canFetchTransactionInfo()) { - $method->fetchTransactionInfo( - $payment, - $invoice->getTransactionId() - ); - } - } - - if ($invoice->getIsPaid()) { - throw new \Magento\Framework\Exception\LocalizedException( - __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) - ); - } - - // attempt to capture: this can trigger "is_transaction_pending" - $method = $payment->getMethodInstance(); - $method->setStore( - $order->getStoreId() - ); - //TODO replace for sale usage - $method->capture($payment, $amountToCapture); - - // prepare parent transaction and its amount - $paidWorkaround = 0; - if (!$invoice->wasPayCalled()) { - $paidWorkaround = (double)$amountToCapture; - } - if ($payment->isCaptureFinal($paidWorkaround)) { - $payment->setShouldCloseParentTransaction(true); - } - - $transactionBuilder = $this->transactionBuilder->setPayment($payment); - $transactionBuilder->setOrder($order); - $transactionBuilder->setFailSafe(true); - $transactionBuilder->setTransactionId($payment->getTransactionId()); - $transactionBuilder->setAdditionalInformation($payment->getTransactionAdditionalInfo()); - $transactionBuilder->setSalesDocument($invoice); - $transaction = $transactionBuilder->build(Transaction::TYPE_CAPTURE); - - $message = $this->stateCommand->execute($payment, $amountToCapture, $order); - if ($payment->getIsTransactionPending()) { - $invoice->setIsPaid(false); - } else { - $invoice->setIsPaid(true); - $this->updateTotals($payment, ['base_amount_paid_online' => $amountToCapture]); - } - $message = $payment->prependMessage($message); - $payment->addTransactionCommentsToOrder($transaction, $message); - $invoice->setTransactionId($payment->getLastTransId()); - return $payment; + return $this->processInvoiceOperation->execute($payment, $invoice, 'capture'); } } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/ProcessInvoiceOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/ProcessInvoiceOperation.php new file mode 100644 index 0000000000000..83565bbb1698e --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/ProcessInvoiceOperation.php @@ -0,0 +1,115 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\Order\Payment\Operations; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Sales\Api\Data\InvoiceInterface; +use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Transaction; + +/** + * Processes invoice created by SaleOperation or CaptureOperation. + */ +class ProcessInvoiceOperation extends AbstractOperation +{ + /** + * Processes invoice and makes call to payment gateway. + * + * @param OrderPaymentInterface $payment + * @param InvoiceInterface $invoice + * @param string $operationMethod + * @return OrderPaymentInterface + * @throws LocalizedException + */ + public function execute( + OrderPaymentInterface $payment, + InvoiceInterface $invoice, + string $operationMethod + ): OrderPaymentInterface { + /** + * @var $payment Payment + */ + $amountToCapture = $payment->formatAmount($invoice->getBaseGrandTotal(), true); + $order = $payment->getOrder(); + + $payment->setTransactionId( + $this->transactionManager->generateTransactionId( + $payment, + Transaction::TYPE_CAPTURE, + $payment->getAuthorizationTransaction() + ) + ); + + $this->eventManager->dispatch( + 'sales_order_payment_capture', + ['payment' => $payment, 'invoice' => $invoice] + ); + + /** + * Fetch an update about existing transaction. It can determine whether the transaction can be paid + * Capture attempt will happen only when invoice is not yet paid and the transaction can be paid + */ + if ($invoice->getTransactionId()) { + $method = $payment->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + if ($method->canFetchTransactionInfo()) { + $method->fetchTransactionInfo( + $payment, + $invoice->getTransactionId() + ); + } + } + + if ($invoice->getIsPaid()) { + throw new LocalizedException( + __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) + ); + } + + // attempt to capture: this can trigger "is_transaction_pending" + $method = $payment->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + + $method->$operationMethod($payment, $amountToCapture); + + // prepare parent transaction and its amount + $paidWorkaround = 0; + if (!$invoice->wasPayCalled()) { + $paidWorkaround = (double)$amountToCapture; + } + if ($payment->isCaptureFinal($paidWorkaround)) { + $payment->setShouldCloseParentTransaction(true); + } + + $transactionBuilder = $this->transactionBuilder->setPayment($payment); + $transactionBuilder->setOrder($order); + $transactionBuilder->setFailSafe(true); + $transactionBuilder->setTransactionId($payment->getTransactionId()); + $transactionBuilder->setAdditionalInformation($payment->getTransactionAdditionalInfo()); + $transactionBuilder->setSalesDocument($invoice); + $transaction = $transactionBuilder->build(Transaction::TYPE_CAPTURE); + + $message = $this->stateCommand->execute($payment, $amountToCapture, $order); + if ($payment->getIsTransactionPending()) { + $invoice->setIsPaid(false); + } else { + $invoice->setIsPaid(true); + $this->updateTotals($payment, ['base_amount_paid_online' => $amountToCapture]); + } + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + $invoice->setTransactionId($payment->getLastTransId()); + + return $payment; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/SaleOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/SaleOperation.php new file mode 100644 index 0000000000000..7ff271078eda6 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/SaleOperation.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\Order\Payment\Operations; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Payment; + +/** + * Perform 'sale' payment operation. + */ +class SaleOperation +{ + /** + * @var ProcessInvoiceOperation + */ + private $processInvoiceOperation; + + /** + * @param ProcessInvoiceOperation $processInvoiceOperation + */ + public function __construct( + ProcessInvoiceOperation $processInvoiceOperation + ) { + $this->processInvoiceOperation = $processInvoiceOperation; + } + + /** + * Authorize and Capture payment. + * + * @param OrderPaymentInterface $payment + * @return OrderPaymentInterface + * @throws LocalizedException + */ + public function execute(OrderPaymentInterface $payment): OrderPaymentInterface + { + /** @var $payment Payment */ + $invoice = $payment->getOrder()->prepareInvoice(); + $invoice->register(); + $this->processInvoiceOperation->execute($payment, $invoice, 'sale'); + if ($invoice->getIsPaid()) { + $invoice->pay(); + } + $payment->getOrder()->addRelatedObject($invoice); + $payment->setCreatedInvoice($invoice); + if ($payment->getIsFraudDetected()) { + $payment->getOrder()->setStatus(Order::STATUS_FRAUD); + } + + return $payment; + } +} diff --git a/app/code/Magento/Sales/Model/Order/ProductOption.php b/app/code/Magento/Sales/Model/Order/ProductOption.php index dc9ec42e27e60..9a4f847b135e7 100644 --- a/app/code/Magento/Sales/Model/Order/ProductOption.php +++ b/app/code/Magento/Sales/Model/Order/ProductOption.php @@ -59,6 +59,7 @@ public function add(OrderItemInterface $orderItem): void { /** @var DataObject $request */ $request = $orderItem->getBuyRequest(); + $request->setProductOptions($orderItem->getProductOptions()); $productType = $orderItem->getProductType(); if (isset($this->processorPool[$productType]) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php deleted file mode 100644 index 9c261fa31bc25..0000000000000 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Model\ResourceModel\Order\Invoice\Grid; - -use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; -use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; -use Magento\Framework\Event\ManagerInterface as EventManager; -use Magento\Sales\Ui\Component\DataProvider\Document; -use Psr\Log\LoggerInterface as Logger; - -class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult -{ - /** - * @inheritdoc - */ - protected $document = Document::class; - - /** - * Initialize dependencies. - * - * @param EntityFactory $entityFactory - * @param Logger $logger - * @param FetchStrategy $fetchStrategy - * @param EventManager $eventManager - * @param string $mainTable - * @param string $resourceModel - */ - public function __construct( - EntityFactory $entityFactory, - Logger $logger, - FetchStrategy $fetchStrategy, - EventManager $eventManager, - $mainTable = 'sales_invoice_grid', - $resourceModel = \Magento\Sales\Model\ResourceModel\Order\Invoice::class - ) { - parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); - } -} diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml new file mode 100644 index 0000000000000..5b08ba30a8fec --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml @@ -0,0 +1,24 @@ +<?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="AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup" extends="AddSimpleProductToOrderActionGroup"> + <annotations> + <description>Add product to order with custom option type file. Start on create order page.</description> + </annotations> + <arguments> + <argument name="file" type="string" defaultValue="{{TestImageNew.file}}" /> + </arguments> + + <remove keyForRemoval="fillProductQty"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad" after="selectProduct"/> + <fillField selector="{{AdminOrderFormCustomOptionsSection.quantity}}" userInput="{{productQty}}" stepKey="fillProductQty" after="waitForAjaxLoad"/> + <attachFile selector="{{AdminOrderFormCustomOptionsSection.file}}" userInput="{{file}}" stepKey="attachImageForOptional" after="fillProductQty"/> + <click selector="{{AdminOrderFormCustomOptionsSection.buttonOk}}" stepKey="clickButtonOK" after="attachImageForOptional"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertProductQtyInGridActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertProductQtyInGridActionGroup.xml index cffda5665549e..48cbd803470aa 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertProductQtyInGridActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertProductQtyInGridActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminAssertProductQtyInGridActionGroup"> <annotations> - <description>Goes tot he Admin Catalog Product grid page. Filters the grid based on the provided Product SKU. Validates that the provided Product Qty is present.</description> + <description>Goes to the Admin Catalog Product grid page. Filters the grid based on the provided Product SKU. Validates that the provided Product Qty is present.</description> </annotations> <arguments> <argument name="productSku" type="string"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml new file mode 100644 index 0000000000000..fb9f68d861faf --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml @@ -0,0 +1,26 @@ +<?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="AdminChangeCustomerOptionFileActionGroup"> + <annotations> + <description>Change custom option file on admin order page.</description> + </annotations> + <arguments> + <argument name="file" type="string" defaultValue="{{TestImageNew.file}}" /> + </arguments> + + <click selector="{{AdminOrderFormItemsSection.configure}}" stepKey="clickConfigure"/> + <waitForAjaxLoad stepKey="waitForAjaxLoad"/> + <click selector="{{AdminOrderFormCustomOptionsSection.linkChange}}" stepKey="clickLinkChange"/> + <waitForPageLoad stepKey="waitForChangeLoad"/> + <attachFile selector="{{AdminOrderFormCustomOptionsSection.file}}" userInput="{{file}}" stepKey="changeAttachImage"/> + <click selector="{{AdminOrderFormCustomOptionsSection.buttonOk}}" stepKey="clickButtonOK"/> + <waitForPageLoad stepKey="waitForCustomOptionApplied"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreateInvoiceAndCreditMemoActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreateInvoiceAndCreditMemoActionGroup.xml index a69cd8688c6c5..c4e70a1cacd1c 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreateInvoiceAndCreditMemoActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminCreateInvoiceAndCreditMemoActionGroup.xml @@ -13,7 +13,7 @@ <waitForPageLoad stepKey="waitForLoadingCreditMemoPage" after="pushButtonCreditMemo"/> <scrollTo selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="scrollToBottom" after="waitForLoadingCreditMemoPage"/> <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickSubmitRefund" after="scrollToBottom"/> - <waitForPageLoad stepKey="waitForMainOrderPageLoad" after="clickSubmitRefund"/> + <waitForPageLoad stepKey="waitForMainOrderPageLoad" after="clickSubmitRefund" time="60"/> <see userInput="You created the credit memo." stepKey="seeCreditMemoMessage" after="waitForMainOrderPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorActionGroup.xml new file mode 100644 index 0000000000000..a2f35b9c5fca8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AssertAdminItemOrderedErrorActionGroup"> + <annotations> + <description>Assert that item in "Item Ordered" grid has an error/notice</description> + </annotations> + <arguments> + <argument name="productName" defaultValue="{{_defaultProduct.name}}" type="string"/> + <argument name="messageType" defaultValue="error" type="string"/> + <argument name="message" defaultValue="The requested qty is not available" type="string"/> + </arguments> + <see userInput="{{message}}" selector="{{AdminOrderFormItemsOrderedSection.productMessage(productName, messageType)}}" stepKey="assertItemErrorVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorNotVisibleActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorNotVisibleActionGroup.xml new file mode 100644 index 0000000000000..83bac652d7dff --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminItemOrderedErrorNotVisibleActionGroup.xml @@ -0,0 +1,21 @@ +<?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="AssertAdminItemOrderedErrorNotVisibleActionGroup"> + <annotations> + <description>Assert that item in "Item Ordered" grid does not have an error/notice</description> + </annotations> + <arguments> + <argument name="productName" defaultValue="{{_defaultProduct.name}}" type="string"/> + <argument name="messageType" defaultValue="error" type="string"/> + <argument name="message" defaultValue="The requested qty is not available" type="string"/> + </arguments> + <dontSee userInput="{{message}}" selector="{{AdminOrderFormItemsOrderedSection.productMessage(productName, messageType)}}" stepKey="assertItemErrorNotVisible"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/NavigateToNewOrderPageExistingCustomerActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/NavigateToNewOrderPageExistingCustomerActionGroup.xml index a8f9d61ad6803..220d47e0495f9 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/NavigateToNewOrderPageExistingCustomerActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/NavigateToNewOrderPageExistingCustomerActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="NavigateToNewOrderPageExistingCustomerActionGroup"> <annotations> - <description>Goes tot he Admin Orders grid page. Clicks on 'Create New Order'. Filters the grid for the provided Customer. Clicks on the Customer. Selects the provided Store View, if present. Validates that the Page Title is present and correct.</description> + <description>Goes to the Admin Orders grid page. Clicks on 'Create New Order'. Filters the grid for the provided Customer. Clicks on the Customer. Selects the provided Store View, if present. Validates that the Page Title is present and correct.</description> </annotations> <arguments> <argument name="customer"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml index 680d44ebb34fe..a7e2b2ec1f0d9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminOrderCreatePage.xml @@ -20,5 +20,6 @@ <section name="AdminOrderFormStoreSelectorSection"/> <section name="AdminOrderFormDiscountSection"/> <section name="AdminOrderFormMessagesSection"/> + <section name="AdminOrderFormCustomOptionsSection"/> </page> </pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml index 45fdfebfa8145..ecdf9e34de55a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml @@ -11,6 +11,7 @@ <section name="AdminOrderDetailsMainActionsSection"> <element name="back" type="button" selector="#back" timeout="30"/> <element name="cancel" type="button" selector="#order-view-cancel-button" timeout="30"/> + <element name="orderEntityId" type="input" selector="#sales_order_view input[name='order_id']" timeout="30"/> <element name="sendEmail" type="button" selector="#send_notification" timeout="30"/> <element name="creditMemo" type="button" selector="#order_creditmemo" timeout="30"/> <element name="hold" type="button" selector="#order-view-hold-button" timeout="30"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml new file mode 100644 index 0000000000000..066aa4181e7ef --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml @@ -0,0 +1,16 @@ +<?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="AdminOrderFormCustomOptionsSection"> + <element name="quantity" type="input" selector="//input[@id='product_composite_configure_input_qty']"/> + <element name="file" type="file" selector="//input[@type='file'][contains(@class, 'product-custom-option')]" /> + <element name="buttonOk" type="button" selector="//button[contains(@class, 'action-primary')][@data-role='action']"/> + <element name="linkChange" type="text" selector="//div[contains(@class, 'entry-edit')]//a[contains(text(),'Change')]"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml index e3417e7c662b9..4437f6e6775f2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsOrderedSection.xml @@ -18,5 +18,6 @@ <element name="configureSelectAttribute" type="select" selector="select[id*=attribute]"/> <element name="itemsSKU" type="text" selector="(//div[contains(@class, 'product-sku-block')])[{{productNumber}}]" parameterized="true"/> <element name="moveProduct" type="select" selector="//td[contains(.,'{{productName}}')]/../..//td//select" parameterized="true"/> + <element name="productMessage" type="text" selector="//section[@id = 'order-items']//span[text()='{{productName}}']/ancestor::tr/..//div[contains(@class, 'message-{{messageType}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml index d262dfa9b010c..d1c94965640c5 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderDetailsSection.xml @@ -9,6 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontOrderDetailsSection"> + <element name="orderDateTagElement" type="block" selector=".order-date date"/> <element name="orderDetailsBlock" type="block" selector=".block-order-details-view"/> <element name="billingAddressBlock" type="block" selector=".box-order-billing-address > .box-content > address"/> <element name="discountSalesRule" type="text" selector="tr.discount span.price"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml index a15e176c943ab..9b03f566a5c57 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml @@ -57,7 +57,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> @@ -72,7 +72,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <magentoCLI command="cron:run --group=index" stepKey="runCron"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml index 589da3e49dc89..1485613f4e4c2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml @@ -28,7 +28,7 @@ </before> <after> <!-- Admin log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer log out --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAddSelectedProductToOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAddSelectedProductToOrderTest.xml new file mode 100644 index 0000000000000..ca74eca88308a --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAddSelectedProductToOrderTest.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminAddSelectedProductToOrderTest"> + <annotations> + <features value="CatalogInventory"/> + <stories value="Admin create order"/> + <title value="Add selected products to order in Admin when requested qty more than available"/> + <description value="Trying to add selected products to order in Admin when requested qty more than available"/> + <useCaseId value="MC-29184"/> + <testCaseId value="MC-31589"/> + <severity value="MAJOR"/> + <group value="sales"/> + <group value="catalogInventory"/> + </annotations> + <before> + <createData entity="Simple_US_Customer" stepKey="simpleCustomer"/> + <createData entity="SimpleProduct2" stepKey="simpleProduct"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> + <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + + <!-- Initiate create new order --> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPageWithExistingCustomer"> + <argument name="customer" value="$simpleCustomer$"/> + </actionGroup> + <!-- Add to order maximum available quantity - 1 --> + <executeJS function="return {{SimpleProduct2.quantity}} - 1" stepKey="maxQtyMinusOne"/> + <actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addProductToOrderWithMaxQtyMinusOne"> + <argument name="product" value="$simpleProduct$"/> + <argument name="productQty" value="{$maxQtyMinusOne}"/> + </actionGroup> + <!-- Check that there is no error or notice --> + <actionGroup ref="AssertAdminItemOrderedErrorNotVisibleActionGroup" stepKey="assertNoticeAbsent"> + <argument name="productName" value="$simpleProduct.name$"/> + <argument name="messageType" value="notice"/> + </actionGroup> + <actionGroup ref="AssertAdminItemOrderedErrorNotVisibleActionGroup" stepKey="assertErrorAbsent"> + <argument name="productName" value="$simpleProduct.name$"/> + <argument name="messageType" value="error"/> + </actionGroup> + <!-- Add to order maximum available quantity --> + <actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addProductToOrder"> + <argument name="product" value="$simpleProduct$"/> + <argument name="productQty" value="1"/> + </actionGroup> + <!-- Check that there is no error or notice --> + <actionGroup ref="AssertAdminItemOrderedErrorNotVisibleActionGroup" stepKey="assertNoticeAbsentAgain"> + <argument name="productName" value="$simpleProduct.name$"/> + <argument name="messageType" value="notice"/> + </actionGroup> + <actionGroup ref="AssertAdminItemOrderedErrorNotVisibleActionGroup" stepKey="assertErrorAbsentAgain"> + <argument name="productName" value="$simpleProduct.name$"/> + <argument name="messageType" value="error"/> + </actionGroup> + <!-- Add to order one more quantity --> + <actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addProductToOrderAgain"> + <argument name="product" value="$simpleProduct$"/> + <argument name="productQty" value="1"/> + </actionGroup> + <!-- Check that error remains --> + <actionGroup ref="AssertAdminItemOrderedErrorActionGroup" stepKey="assertProductErrorRemains"> + <argument name="productName" value="$simpleProduct.name$"/> + <argument name="messageType" value="notice"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml index ec518c79a0808..9b12f1c951991 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAvailabilityCreditMemoWithNoPaymentTest.xml @@ -38,7 +38,7 @@ <argument name="customerEmail" value="Simple_US_Customer.email"/> </actionGroup> <magentoCLI command="cache:flush" stepKey="flushCache"/> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> </after> <!--Proceed to Admin panel > SALES > Orders. Created order should be in Processing status--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithBankTransferPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithBankTransferPaymentMethodTest.xml index 726b4a99cdec9..4646f6cf2e5a0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithBankTransferPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithBankTransferPaymentMethodTest.xml @@ -40,7 +40,7 @@ <magentoCLI command="config:set {{DisablePaymentBankTransferConfigData.path}} {{DisablePaymentBankTransferConfigData.value}}" stepKey="disableBankTransferPayment"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest.xml index eb46621a458ab..7f162ca4e2a6a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCashOnDeliveryPaymentMethodTest.xml @@ -40,7 +40,7 @@ <magentoCLI command="config:set {{DisableCashOnDeliveryConfigData.path}} {{DisableCashOnDeliveryConfigData.value}}" stepKey="disableCashOnDeliveryPayment"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create new customer order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml index b303364bbf324..d08754a8a4127 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml @@ -107,7 +107,10 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create new customer order --> <comment userInput="Create new customer order" stepKey="createNewCustomerOrderComment"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithProductQtyWithoutStockDecreaseTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithProductQtyWithoutStockDecreaseTest.xml index a8076bfb9f681..d64af533b04e0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithProductQtyWithoutStockDecreaseTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithProductQtyWithoutStockDecreaseTest.xml @@ -43,7 +43,7 @@ <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithPurchaseOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithPurchaseOrderPaymentMethodTest.xml index c85a3fffc2c69..ce653b11f854b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithPurchaseOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithPurchaseOrderPaymentMethodTest.xml @@ -42,7 +42,7 @@ <magentoCLI command="config:set {{DisablePurchaseOrderConfigData.path}} {{DisablePurchaseOrderConfigData.value}}" stepKey="disablePurchaseOrderPayment"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithZeroSubtotalCheckoutTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithZeroSubtotalCheckoutTest.xml index a8014466c5773..095bd9af2c1b1 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithZeroSubtotalCheckoutTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithZeroSubtotalCheckoutTest.xml @@ -45,7 +45,7 @@ <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml index e19002d5ecb4c..cabb6edec2f52 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupInNewOrder.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="NavigateToNewOrderPageNewCustomerActionGroup" stepKey="openNewOrder"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml index 251d29df43dd1..34a415ccf03ad 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml @@ -32,7 +32,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!--Delete customer--> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateOrderActionGroup" stepKey="createOrder"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml index ad3b6cf45d5bb..979e2cef3ff28 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingDateAfterChangeInterfaceLocaleTest.xml @@ -40,7 +40,7 @@ <!--Clear filters--> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> <!--Logout from Admin page--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml index e499f72004986..e55cdfeb284b4 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml @@ -48,7 +48,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> </after> <!--Complete Bundle product creation--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml index 4b582a09deacf..de92d80546733 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Order --> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPage"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml index 2a841b04bd647..9c3aea8bc912e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml @@ -14,17 +14,12 @@ <title value="Create Credit Memo for Offline Payment Methods"/> <description value="Create CreditMemo return to stock only one unit of configurable product"/> <severity value="CRITICAL"/> - <testCaseId value="MC-15865"/> + <testCaseId value="MC-28444"/> <group value="sales"/> <group value="mtf_migrated"/> </annotations> <before> - <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> - - <!-- Create Data --> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> - - <!-- Create the category --> <createData entity="ApiCategory" stepKey="createCategory"/> <!-- Create the configurable product and add it to the category --> @@ -88,6 +83,7 @@ <!-- Enable payment method one of "Check/Money Order" and shipping method one of "Flat Rate" --> <magentoCLI command="config:set {{enabledCheckMoneyOrder.label}} {{enabledCheckMoneyOrder.value}}" stepKey="enableCheckMoneyOrder"/> <createData entity="FlatRateShippingMethodConfig" stepKey="enableFlatRate"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> <!-- Delete data --> @@ -97,7 +93,11 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create Order --> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPage"> @@ -106,9 +106,9 @@ <!--Add configurable product to order--> <actionGroup ref="AddConfigurableProductToOrderFromAdminActionGroup" stepKey="addConfigurableProductToOrder"> - <argument name="product" value="$$createConfigProduct$$"/> - <argument name="attribute" value="$$createConfigProductAttribute$$"/> - <argument name="option" value="$$getConfigAttributeOption1$$"/> + <argument name="product" value="$createConfigProduct$"/> + <argument name="attribute" value="$createConfigProductAttribute$"/> + <argument name="option" value="$getConfigAttributeOption1$"/> </actionGroup> <actionGroup ref="FillOrderCustomerInformationActionGroup" stepKey="fillCustomerInfo"> @@ -118,19 +118,16 @@ <actionGroup ref="OrderSelectFlatRateShippingActionGroup" stepKey="selectFlatRate"/> <click selector="{{OrdersGridSection.submitOrder}}" stepKey="submitOrder"/> <waitForPageLoad stepKey="waitForSubmitOrderPage"/> - <see stepKey="seeSuccessMessageForOrder" userInput="You created the order."/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageForOrderAppears"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You created the order." stepKey="seeSuccessMessageForOrder"/> <!-- Create Invoice --> <actionGroup ref="StartCreateInvoiceFromOrderPageActionGroup" stepKey="startInvoice"/> - <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> - <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForMessageAppears"/> - <see selector="{{AdminMessagesSection.success}}" userInput="The invoice has been created." stepKey="seeInvoiceCreateSuccess"/> + <actionGroup ref="SubmitInvoiceActionGroup" stepKey="clickSubmitInvoice"/> <!-- Go to Sales > Orders > find out placed order and open --> - <grabTextFrom selector="|Order # (\d+)|" stepKey="grabOrderId" /> - <assertNotEmpty actual="$grabOrderId" stepKey="assertOrderIdIsNotEmpty" after="grabOrderId"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openOrder"> - <argument name="orderId" value="{$grabOrderId}"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> + <argument name="entityId" value="{$grabOrderIdClickSubmitInvoice}"/> </actionGroup> <!-- Click 'Credit Memo' button and fill data from dataset: partial refund --> @@ -140,11 +137,7 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> - - <!-- Perform all assertions: assert refund success create message --> - <see selector="{{AdminIndexManagementSection.successMessage}}" userInput="You created the credit memo." stepKey="assertRefundSuccessCreateMessage"/> + <actionGroup ref="SubmitCreditMemoActionGroup" stepKey="clickRefundOffline"/> <!-- Assert product Qty decreased after CreditMemo --> <actionGroup ref="AdminAssertProductQtyInGridActionGroup" stepKey="assertQtyDecreased"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml index 2b6008c93084e..2cacfe934427c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml @@ -37,7 +37,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Order --> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderPage"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithCashOnDeliveryTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithCashOnDeliveryTest.xml index 452c54d188c57..e9954de55afbc 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithCashOnDeliveryTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithCashOnDeliveryTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml index 231ff78d7d8fb..2d5b2d3c66906 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index 73c126bb7794f..9a635df80f108 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -25,7 +25,7 @@ </createData> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteProduct1"/> <deleteData createDataKey="createProduct" stepKey="deleteCategory1"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAddProductCheckboxTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAddProductCheckboxTest.xml index 8fe49558cf091..072522452e7b9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAddProductCheckboxTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAddProductCheckboxTest.xml @@ -42,7 +42,7 @@ <seeCheckboxIsChecked selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" stepKey="verifyProductChecked"/> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createSimpleCustomer" stepKey="deleteSimpleCustomer"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml index 338765d650d13..a7112776bf157 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderAndCheckTheReorderTest.xml @@ -52,7 +52,7 @@ <actionGroup ref="StorefrontCustomerReorderButtonNotVisibleActionGroup" stepKey="checkReorderButton"/> <after> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <magentoCLI command="config:set payment/cashondelivery/active 0" stepKey="disableCashOnDeliveryMethod"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderForCustomerWithTwoAddressesTaxableAndNonTaxableTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderForCustomerWithTwoAddressesTaxableAndNonTaxableTest.xml index 8177bbaa6e1d7..b687e63fbc328 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderForCustomerWithTwoAddressesTaxableAndNonTaxableTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderForCustomerWithTwoAddressesTaxableAndNonTaxableTest.xml @@ -71,7 +71,7 @@ <!--Delete tax rule--> <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> <!--Logout--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!--Disable free shipping method --> <magentoCLI command="config:set {{DisableFreeShippingConfigData.path}} {{DisableFreeShippingConfigData.value}}" stepKey="disableFreeShipping"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml index 40a731410a899..bbb0489b6c9a4 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to new order status page --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml index d1381bbb1efb0..23bf293f67a81 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to new order status page --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml index c2daaac84dd42..03acf2194c64d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to new order status page --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithBundleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithBundleProductTest.xml index 1749fcd6c218e..f439d792c9330 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithBundleProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithBundleProductTest.xml @@ -101,7 +101,7 @@ <actionGroup ref="VerifyCreatedOrderInformationActionGroup" stepKey="verifyCreatedOrderInformation"/> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="product" stepKey="delete"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml index 1fa01e0efa156..677969fd00d91 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml @@ -14,6 +14,7 @@ <title value="Admin create order with date time option UI test"/> <description value="Check asterisk rendered correctly for Product with custom option (datetime) at backend"/> <features value="Sales"/> + <stories value="Create order in Admin"/> <severity value="MINOR"/> <group value="Sales"/> </annotations> @@ -28,7 +29,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteSimpleCustomer"/> </after> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml index 58a680ea61c87..60ade9ebe01e7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSelectedShoppingCartItemsTest.xml @@ -97,7 +97,7 @@ <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <!--Logout--> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml new file mode 100644 index 0000000000000..b694363960def --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml @@ -0,0 +1,52 @@ +<?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="AdminCreateOrderWithSimpleProductCustomOptionFileTest"> + <annotations> + <title value="Create Order with simple product with custom option."/> + <description value="Verify, admin able to change file for custom option during order creation."/> + <features value="Sales"/> + <severity value="MAJOR"/> + <group value="Sales"/> + </annotations> + <before> + <!--Create test data.--> + <createData entity="_defaultCategory" stepKey="category"/> + <createData entity="SimpleProduct" stepKey="simpleProduct"> + <requiredEntity createDataKey="category"/> + </createData> + <createData entity="Simple_US_Customer_CA" stepKey="customer"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!--Clean up created test data.--> + <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer" /> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Add option to product.--> + <amOnPage url="{{AdminProductEditPage.url($simpleProduct.id$)}}" stepKey="navigateToProductEditPage"/> + <actionGroup ref="AddProductCustomOptionFileActionGroup" stepKey="addOption"> + <argument name="option" value="ProductOptionFile"/> + </actionGroup> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <!--Create order.--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="navigateToNewOrderWithExistingCustomer"> + <argument name="customer" value="$customer$"/> + </actionGroup> + <actionGroup ref="AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$simpleProduct$"/> + <argument name="productQty" value="$simpleProduct.quantity$"/> + </actionGroup> + <!--Verify, admin able to change file for custom option.--> + <actionGroup ref="AdminChangeCustomerOptionFileActionGroup" stepKey="changeFile"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml index 76f916d55ee92..cc709dc6e16eb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductTest.xml @@ -50,7 +50,7 @@ <argument name="stockStatus" value="Out of Stock"/> </actionGroup> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set payment/cashondelivery/active 0" stepKey="disableCashOnDeliveryMethod"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminFreeShippingNotAvailableIfMinimumOrderAmountNotMatchOrderTotalTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminFreeShippingNotAvailableIfMinimumOrderAmountNotMatchOrderTotalTest.xml index 9ff6f3bdac985..01a27a6191d74 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminFreeShippingNotAvailableIfMinimumOrderAmountNotMatchOrderTotalTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminFreeShippingNotAvailableIfMinimumOrderAmountNotMatchOrderTotalTest.xml @@ -37,7 +37,7 @@ <createData entity="FlatRateShippingMethodConfig" stepKey="enableFlatRate"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShippingMethod"/> <createData entity="setFreeShippingSubtotalToDefault" stepKey="setFreeShippingSubtotalToDefault"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="cache:flush" stepKey="flushCache2"/> </after> <!--Create new order with existing customer--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminHoldCreatedOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminHoldCreatedOrderTest.xml index 5dc5dbf3ab79d..a5cbb15faf2d7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminHoldCreatedOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminHoldCreatedOrderTest.xml @@ -40,7 +40,7 @@ <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> <deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new customer order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml index ec624a80f1613..803e24b3423aa 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelCompleteAndClosedTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create first order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml index 5e524bcf6e05c..c230dc41f0d2e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersCancelProcessingAndClosedTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create first order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml index 179e1aa35a4e9..14b61af59eaed 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnCompleteTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml index ec0ec8ca222da..5ac803cb666b4 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersHoldOnPendingAndProcessingTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create first order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml index 6c97c4add6313..4b8df455d545d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersReleasePendingOrderTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml index d7c9664b8bce2..84d5426bd44e3 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminMassOrdersUpdateCancelPendingOrderTest.xml @@ -32,7 +32,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml index 009f86256a910..83998990c70ed 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml @@ -33,7 +33,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminProductInTheShoppingCartCouldBeReachedByAdminDuringOrderCreationWithMultiWebsiteConfigTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminProductInTheShoppingCartCouldBeReachedByAdminDuringOrderCreationWithMultiWebsiteConfigTest.xml index d30074a240546..4f0d777ad0f21 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminProductInTheShoppingCartCouldBeReachedByAdminDuringOrderCreationWithMultiWebsiteConfigTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminProductInTheShoppingCartCouldBeReachedByAdminDuringOrderCreationWithMultiWebsiteConfigTest.xml @@ -53,7 +53,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create customer account for Second Website--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml similarity index 68% rename from app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml rename to app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml index dc74e024b2629..b535e1836ed24 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml @@ -7,23 +7,26 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminReorderWithCatalogPriceTest"> + <test name="AdminReorderWithCatalogPriceRuleDiscountTest"> <annotations> <features value="Sales"/> <stories value="Admin create order"/> <title value="Reorder doesn't show discount price in Order Totals block"/> <description value="Reorder doesn't show discount price in Order Totals block"/> <severity value="CRITICAL"/> - <testCaseId value="MC-16695"/> + <testCaseId value="MC-28642"/> <useCaseId value="MAGETWO-99691"/> <group value="sales"/> <group value="catalogRule"/> </annotations> + <before> - <!--Create the catalog price rule --> - <createData entity="CatalogRuleToPercent" stepKey="createCatalogRule"/> <!--Create product--> <createData entity="SimpleProduct2" stepKey="createSimpleProductApi"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <!--Create the catalog price rule --> + <createData entity="CatalogRuleToPercent" stepKey="createCatalogRule"/> <!--Create order via API--> <createData entity="GuestCart" stepKey="createGuestCart"/> <createData entity="SimpleCartItem" stepKey="addCartItem"> @@ -36,39 +39,29 @@ <updateData createDataKey="createGuestCart" entity="GuestOrderPaymentMethod" stepKey="sendGuestPaymentInformation"> <requiredEntity createDataKey="createGuestCart"/> </updateData> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> <!--END Create order via API--> </before> + <after> <deleteData createDataKey="createSimpleProductApi" stepKey="deleteSimpleProductApi"/> - <!-- Delete the rule --> - <actionGroup ref="RemoveCatalogPriceRuleActionGroup" stepKey="deletePriceRule"> - <argument name="ruleName" value="{{CatalogRuleToPercent.name}}" /> - </actionGroup> - <!--Clear all filters in grid--> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetCatalogRuleGridFilters"/> - <amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> - <!-- Login as admin --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <!--Open order page by Id--> + + <!--Open order by Id--> <amOnPage url="{{AdminOrderPage.url($createGuestCart.return$)}}" stepKey="navigateToOrderPage"/> - <waitForPageLoad stepKey="waitForCreatedOrderPage"/> <!--Reorder--> <click selector="{{AdminOrderDetailsMainActionsSection.reorder}}" stepKey="clickReorder"/> <!--Verify order item row--> <waitForElementVisible selector="{{AdminOrderItemsOrderedSection.productPrice('2')}}" stepKey="waitOrderItemPriceToBeVisible"/> - <see selector="{{AdminOrderItemsOrderedSection.productPrice('2')}}" userInput="${{AdminOrderSimpleProductWithCatalogRule.subtotal}}" stepKey="seeOrderItemPrice"/> + <see selector="{{AdminOrderItemsOrderedSection.productPrice('2')}}" userInput="{{AdminOrderSimpleProductWithCatalogRule.subtotal}}" stepKey="seeOrderItemPrice"/> <!--Verify totals on Order page--> <scrollTo selector="{{AdminOrderFormTotalSection.grandTotal}}" stepKey="scrollToOrderGrandTotal"/> <waitForElementVisible selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" stepKey="waitOrderSubtotalToBeVisible"/> - <see selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" userInput="${{AdminOrderSimpleProductWithCatalogRule.subtotal}}" stepKey="seeOrderSubTotal"/> + <see selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" userInput="{{AdminOrderSimpleProductWithCatalogRule.subtotal}}" stepKey="seeOrderSubTotal"/> <waitForElementVisible selector="{{AdminOrderFormTotalSection.total('Shipping')}}" stepKey="waitOrderShippingToBeVisible"/> - <see selector="{{AdminOrderFormTotalSection.total('Shipping')}}" userInput="${{AdminOrderSimpleProductWithCatalogRule.shipping}}" stepKey="seeOrderShipping"/> + <see selector="{{AdminOrderFormTotalSection.total('Shipping')}}" userInput="{{AdminOrderSimpleProductWithCatalogRule.shipping}}" stepKey="seeOrderShipping"/> <waitForElementVisible selector="{{AdminOrderFormTotalSection.grandTotal}}" stepKey="waitOrderGrandTotalToBeVisible"/> - <see selector="{{AdminOrderFormTotalSection.grandTotal}}" userInput="${{AdminOrderSimpleProductWithCatalogRule.grandTotal}}" stepKey="seeCorrectGrandTotal"/> + <see selector="{{AdminOrderFormTotalSection.grandTotal}}" userInput="{{AdminOrderSimpleProductWithCatalogRule.grandTotal}}" stepKey="seeCorrectGrandTotal"/> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesCreditMemosNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesCreditMemosNavigateMenuTest.xml index af7cc1822d215..424b931314b01 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesCreditMemosNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesCreditMemosNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSalesCreditMemosPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesInvoicesNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesInvoicesNavigateMenuTest.xml index 5a38a66d1f4b2..89d4cc4c7371f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesInvoicesNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesInvoicesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSalesInvoicesPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesOrdersNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesOrdersNavigateMenuTest.xml index 8099254923a2c..6d765537494ed 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesOrdersNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesOrdersNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSalesOrderPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesShipmentsNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesShipmentsNavigateMenuTest.xml index 5717c6c90fc17..05f15ad76b07c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesShipmentsNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesShipmentsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSalesShipmentsPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesTransactionsNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesTransactionsNavigateMenuTest.xml index 68933be92efe6..17f0bad87037e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesTransactionsNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSalesTransactionsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSalesTransactionsPage"> <argument name="menuUiId" value="{{AdminMenuSales.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSaveInAddressBookCheckboxStateTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSaveInAddressBookCheckboxStateTest.xml index f2341278becba..ac0af3f5b80db 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSaveInAddressBookCheckboxStateTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSaveInAddressBookCheckboxStateTest.xml @@ -27,7 +27,7 @@ <createData entity="ApiSimpleProduct" stepKey="createSimpleProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> </before> <after> <!-- Delete created data and log out --> @@ -35,7 +35,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> </after> <!-- Create new order and choose an existing customer --> <comment userInput="Create new order and choose an existing customer" stepKey="createOrderAndAddCustomer"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminStoresOrderStatusNavigateMenuTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminStoresOrderStatusNavigateMenuTest.xml index d55cde1449033..7884926946178 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminStoresOrderStatusNavigateMenuTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminStoresOrderStatusNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresOrderStatusPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml index 65bba7512e228..cfdbd39838ecb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml @@ -122,7 +122,7 @@ <actionGroup ref="VerifyCreatedOrderInformationActionGroup" stepKey="verifyCreatedOrderInformation"/> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="simpleCustomer" stepKey="deleteSimpleCustomer"/> @@ -131,6 +131,9 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderPaymentMethodValidationTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderPaymentMethodValidationTest.xml index b2d424ca5d7d3..5981c49345aa0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderPaymentMethodValidationTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderPaymentMethodValidationTest.xml @@ -29,7 +29,7 @@ <magentoCLI stepKey="allowSpecificValue" command="config:set payment/cashondelivery/active 0" /> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Create order via Admin--> <comment userInput="Admin creates order" stepKey="adminCreateOrderComment"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutEmailTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutEmailTest.xml index f2d0fffe9b4cf..b9e2d475f9ff6 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutEmailTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutEmailTest.xml @@ -26,7 +26,7 @@ <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Create order via Admin--> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml index 4dbd80a351ee7..d44cb829bc205 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitsOrderWithAndWithoutFieldsValidationTest.xml @@ -25,7 +25,7 @@ <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!--Create order via Admin--> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml index 5f7a7c7606619..bd43937e6f24e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml @@ -21,7 +21,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Go to new order status page--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml index ac377a0d31606..af07d50bcc8c7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml @@ -43,7 +43,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order status --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CheckXSSVulnerabilityDuringOrderCreationTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CheckXSSVulnerabilityDuringOrderCreationTest.xml index 6eb9e37a3ab79..dbe012f17176d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CheckXSSVulnerabilityDuringOrderCreationTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CheckXSSVulnerabilityDuringOrderCreationTest.xml @@ -27,7 +27,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Add product to the shopping cart --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml index 0b065e0da54f0..6cfb2fa5ee911 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml @@ -47,7 +47,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> @@ -143,6 +143,7 @@ <!-- Assert invoiced amount on frontend --> <click selector="{{StorefrontCustomerOrderSection.viewOrder}}" stepKey="clickViewOrder"/> + <dontSeeElement selector="{{StorefrontOrderDetailsSection.orderDateTagElement}}" stepKey="dontSeeDateTag"/> <click selector="{{StorefrontOrderInvoicesSection.invoiceTab}}" stepKey="clickInvoiceTabOnStorefront"/> <see selector="{{StorefrontOrderInvoicesSection.grandTotalPrice}}" userInput="$110.00" stepKey="seePrice"/> </test> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml index 295d388ced96e..3ae4007ac211d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml @@ -47,7 +47,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml index 2ccecf34a5a0c..540af6958d54c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml @@ -45,7 +45,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml index 944a1ed75cebd..8fd751f96914e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml @@ -58,7 +58,7 @@ <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 0fcfa483f1adf..e0ede2ebe55b8 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -89,7 +89,10 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomerIndexPage"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCustomerGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!--Filter and Open the customer edit page --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreditMemoTotalAfterShippingDiscountTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreditMemoTotalAfterShippingDiscountTest.xml index 8ca8dbf21a3a2..8c80c1e9ee6d3 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreditMemoTotalAfterShippingDiscountTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreditMemoTotalAfterShippingDiscountTest.xml @@ -23,7 +23,7 @@ <createData entity="_defaultProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> <actionGroup ref="SetTaxClassForShippingActionGroup" stepKey="setShippingTaxClass"/> </before> @@ -33,7 +33,7 @@ <argument name="ruleName" value="{{ApiSalesRule.name}}"/> </actionGroup> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <deleteData createDataKey="createCategory" stepKey="deleteProduct1"/> <deleteData createDataKey="createProduct" stepKey="deleteCategory1"/> </after> @@ -58,7 +58,7 @@ <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <!-- Place an order from Storefront as a Guest --> <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onCategoryPage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml index 980d5cc82b93d..a214979bef885 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml @@ -86,7 +86,7 @@ </before> <after> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Logout customer --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> @@ -101,6 +101,9 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml index b3c3f045f0d59..6b6718c67cb4c 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml @@ -60,12 +60,15 @@ </before> <after> <!-- Delete created data --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createConfigChildProduct" stepKey="deleteConfigChildProduct"/> <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml index f13a934276e35..5355dba260060 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml @@ -33,7 +33,7 @@ <!-- Delete created data --> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> </after> <!-- Create order --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedBundleFixedProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedBundleFixedProductOnOrderPageTest.xml index 0a39e8a0ac852..bf78012926a7b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedBundleFixedProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedBundleFixedProductOnOrderPageTest.xml @@ -61,7 +61,7 @@ </before> <after> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer logout --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml index aed7447050e5f..eae4de730f116 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml @@ -62,7 +62,7 @@ </before> <after> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Customer logout --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> @@ -80,6 +80,9 @@ <!-- Change configuration --> <magentoCLI command="config:set reports/options/enabled 0" stepKey="disableReportModule"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Login as customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml index 3c01878b59e59..9790f03abed5a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml @@ -33,7 +33,7 @@ </before> <after> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Logout customer --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerDisplayedTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerDisplayedTest.xml index aef3e884c4712..f68a36b29af4f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerDisplayedTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerDisplayedTest.xml @@ -120,7 +120,7 @@ <!-- Delete Customer --> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login to Storefront as Customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml index 3ff8a7791d88b..9319022a96b20 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml @@ -113,7 +113,7 @@ <!-- Delete Customer --> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login to Storefront as Customer --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml index 31f3449866984..2f5ffbb96e8d7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -225,7 +225,10 @@ <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php index dc6fc53e5ec43..dcd80646b168c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -8,7 +8,10 @@ use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; /** - * Test for Magento\Sales\Model\Order\Email\Sender\ShipmentSender class. + * Test for Magento\Sales\Model\Order\Email\Sender\ShipmentSender class + * + * @deprecated since ShipmentSender is deprecated + * @see \Magento\Sales\Model\Order\Email\Sender\ShipmentSender */ class ShipmentSenderTest extends AbstractSenderTest { diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/CaptureOperationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/CaptureOperationTest.php index a2165e6792c45..33d7caf9a94c0 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/CaptureOperationTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/CaptureOperationTest.php @@ -3,116 +3,151 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Sales\Test\Unit\Model\Order\Payment\Operations; -use Magento\Framework\ObjectManager\ObjectManager; -use Magento\Payment\Model\Method; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\MethodInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Operations\CaptureOperation; +use Magento\Sales\Model\Order\Payment\Operations\ProcessInvoiceOperation; +use Magento\Sales\Model\Order\Payment\State\CommandInterface; +use Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface; +use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface as TransactionManagerInterface; class CaptureOperationTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var TransactionManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $transactionManager; + private $transactionManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var EventManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $eventManager; + private $eventManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var BuilderInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $transactionBuilder; + private $transactionBuilder; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CommandInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $stateCommand; + private $stateCommand; /** - * @var \Magento\Sales\Model\Order\Payment\Operations\CaptureOperation + * @var ProcessInvoiceOperation|\PHPUnit_Framework_MockObject_MockObject */ - protected $model; + private $processInvoiceOperation; + + /** + * @var CaptureOperation + */ + private $model; protected function setUp() { - $transactionClass = \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface::class; - $transactionBuilderClass = \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface::class; - $this->transactionManager = $this->getMockBuilder($transactionClass) - ->disableOriginalConstructor() - ->getMock(); - $this->eventManager = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->transactionBuilder = $this->getMockBuilder($transactionBuilderClass) + $this->transactionManager = $this->getMockForAbstractClass(TransactionManagerInterface::class); + $this->eventManager = $this->getMockForAbstractClass(EventManagerInterface::class); + $this->transactionBuilder = $this->getMockForAbstractClass(BuilderInterface::class); + $this->stateCommand = $this->getMockForAbstractClass(CommandInterface::class); + $this->processInvoiceOperation = $this->getMockBuilder(ProcessInvoiceOperation::class) ->disableOriginalConstructor() ->getMock(); - $this->stateCommand = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment\State\CommandInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $objectManagerHelper->getObject( - \Magento\Sales\Model\Order\Payment\Operations\CaptureOperation::class, - [ - 'transactionManager' => $this->transactionManager, - 'eventManager' => $this->eventManager, - 'transactionBuilder' => $this->transactionBuilder, - 'stateCommand' => $this->stateCommand - ] + + $this->model = new CaptureOperation( + $this->stateCommand, + $this->transactionBuilder, + $this->transactionManager, + $this->eventManager, + $this->processInvoiceOperation ); } - public function testCapture() + /** + * Tests a case when capture operation is called with null invoice. + * + * @throws LocalizedException + */ + public function testCaptureWithoutInvoice() { - $baseGrandTotal = 10; - - $order = $this->getMockBuilder(\Magento\Sales\Model\Order::class) + $invoice = $this->getMockBuilder(Invoice::class) ->disableOriginalConstructor() ->getMock(); + $invoice->expects($this->once()) + ->method('register'); + $invoice->expects($this->once()) + ->method('capture'); - $paymentMethod = $this->getMockBuilder(\Magento\Payment\Model\MethodInterface::class) + $order = $this->getMockBuilder(Order::class) + ->setMethods(['prepareInvoice', 'addRelatedObject', 'setStatus']) ->disableOriginalConstructor() ->getMock(); + $order->expects($this->once()) + ->method('prepareInvoice') + ->willReturn($invoice); + $order->expects($this->once()) + ->method('addRelatedObject'); + $order->expects($this->once()) + ->method('setStatus') + ->with(Order::STATUS_FRAUD); + + /** @var MethodInterface $paymentMethod */ + $paymentMethod = $this->getMockForAbstractClass(MethodInterface::class); + $paymentMethod->method('canCapture') + ->willReturn(true); - $orderPayment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class) + /** @var Payment|\PHPUnit_Framework_MockObject_MockObject $orderPayment| */ + $orderPayment = $this->getMockBuilder(Payment::class) + ->setMethods(['setCreatedInvoice', 'getOrder', 'getMethodInstance', 'getIsFraudDetected']) ->disableOriginalConstructor() ->getMock(); - $orderPayment->expects($this->any()) - ->method('formatAmount') - ->with($baseGrandTotal) - ->willReturnArgument(0); - $orderPayment->expects($this->any()) - ->method('getOrder') - ->willReturn($order); - $orderPayment->expects($this->any()) - ->method('getMethodInstance') - ->willReturn($paymentMethod); $orderPayment->expects($this->once()) - ->method('getIsTransactionPending') + ->method('setCreatedInvoice') + ->with($invoice); + $orderPayment->method('getIsFraudDetected') ->willReturn(true); - $orderPayment->expects($this->once()) - ->method('getTransactionAdditionalInfo') - ->willReturn([]); + $orderPayment->method('getOrder') + ->willReturn($order); + $orderPayment->method('getMethodInstance') + ->willReturn($paymentMethod); - $paymentMethod->expects($this->once()) - ->method('capture') - ->with($orderPayment, $baseGrandTotal); + $this->assertInstanceOf( + Payment::class, + $this->model->capture($orderPayment, null) + ); + } - $this->transactionBuilder->expects($this->once()) - ->method('setPayment') - ->with($orderPayment) - ->willReturnSelf(); + /** + * Tests a case when capture operation is called with null invoice. + * + * @throws LocalizedException + */ + public function testCaptureWithInvoice() + { + /** @var Invoice|\PHPUnit_Framework_MockObject_MockObject $invoice */ + $invoice = $this->getMockBuilder(Invoice::class) + ->disableOriginalConstructor() + ->getMock(); - $invoice = $this->getMockBuilder(\Magento\Sales\Model\Order\Invoice::class) + /** @var Payment|\PHPUnit_Framework_MockObject_MockObject $orderPayment| */ + $orderPayment = $this->getMockBuilder(Payment::class) ->disableOriginalConstructor() ->getMock(); - $invoice->expects($this->any()) - ->method('getBaseGrandTotal') - ->willReturn($baseGrandTotal); - $this->model->capture($orderPayment, $invoice); + $this->processInvoiceOperation->expects($this->once()) + ->method('execute') + ->willReturn($orderPayment); + + $this->assertInstanceOf( + Payment::class, + $this->model->capture($orderPayment, $invoice) + ); } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/ProcessInvoiceOperationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/ProcessInvoiceOperationTest.php new file mode 100644 index 0000000000000..511579f0eb90c --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/ProcessInvoiceOperationTest.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Test\Unit\Model\Order\Payment\Operations; + +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\Method\Adapter; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Operations\ProcessInvoiceOperation; +use Magento\Sales\Model\Order\Payment\State\CommandInterface; +use Magento\Sales\Model\Order\Payment\Transaction; +use Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface; +use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface as TransactionManagerInterface; + +class ProcessInvoiceOperationTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var TransactionManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $transactionManager; + + /** + * @var EventManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $eventManager; + + /** + * @var BuilderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $transactionBuilder; + + /** + * @var CommandInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $stateCommand; + + /** + * @var ProcessInvoiceOperation|\PHPUnit_Framework_MockObject_MockObject + */ + protected $model; + + protected function setUp() + { + $this->transactionManager = $this->getMockForAbstractClass(TransactionManagerInterface::class); + $this->eventManager = $this->getMockForAbstractClass(EventManagerInterface::class); + $this->transactionBuilder = $this->getMockForAbstractClass(BuilderInterface::class); + $this->stateCommand = $this->getMockForAbstractClass(CommandInterface::class); + + $this->model = new ProcessInvoiceOperation( + $this->stateCommand, + $this->transactionBuilder, + $this->transactionManager, + $this->eventManager + ); + } + + public function testExecute() + { + $amountToCapture = $baseGrandTotal = 10; + $operationMethod = 'sale'; + $storeId = 1; + $transactionId = '1ASD3456'; + + /** @var Order|\PHPUnit_Framework_MockObject_MockObject $order */ + $order = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + $order->method('getStoreId') + ->willReturn($storeId); + + /** @var Adapter|\PHPUnit_Framework_MockObject_MockObject $paymentMethod */ + $paymentMethod = $this->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + + $orderPayment = $this->getMockBuilder(Payment::class) + ->disableOriginalConstructor() + ->getMock(); + $orderPayment->method('formatAmount') + ->with($baseGrandTotal) + ->willReturnArgument(0); + $orderPayment->method('getOrder') + ->willReturn($order); + $orderPayment->method('getMethodInstance') + ->willReturn($paymentMethod); + $orderPayment->expects($this->once()) + ->method('setTransactionId') + ->with($transactionId); + $authTransaction = $this->createMock(Transaction::class); + $orderPayment->expects($this->once()) + ->method('getAuthorizationTransaction') + ->willReturn($authTransaction); + $orderPayment->expects($this->once()) + ->method('getIsTransactionPending') + ->willReturn(true); + $orderPayment->expects($this->once()) + ->method('getTransactionAdditionalInfo') + ->willReturn([]); + + $this->transactionManager->expects($this->once()) + ->method('generateTransactionId') + ->with($orderPayment, Transaction::TYPE_CAPTURE, $authTransaction) + ->willReturn($transactionId); + + $paymentMethod->method('setStore') + ->with($storeId); + $paymentMethod->expects($this->once()) + ->method($operationMethod) + ->with($orderPayment, $amountToCapture); + + $this->transactionBuilder->expects($this->once()) + ->method('setPayment') + ->with($orderPayment) + ->willReturnSelf(); + + $invoice = $this->getMockBuilder(Invoice::class) + ->disableOriginalConstructor() + ->getMock(); + $invoice->method('getBaseGrandTotal') + ->willReturn($baseGrandTotal); + + $this->model->execute($orderPayment, $invoice, $operationMethod); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/SaleOperationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/SaleOperationTest.php new file mode 100644 index 0000000000000..9e125ecb3d295 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Operations/SaleOperationTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Test\Unit\Model\Order\Payment\Operations; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\MethodInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Operations\SaleOperation; +use Magento\Sales\Model\Order\Payment\Operations\ProcessInvoiceOperation; + +class SaleOperationTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var ProcessInvoiceOperation|\PHPUnit_Framework_MockObject_MockObject + */ + private $processInvoiceOperation; + + /** + * @var SaleOperation + */ + private $model; + + protected function setUp() + { + $this->processInvoiceOperation = $this->getMockBuilder(ProcessInvoiceOperation::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new SaleOperation( + $this->processInvoiceOperation + ); + } + + /** + * Tests a case when 'sale' operation is called with fraud payment. + * + * @throws LocalizedException + * @dataProvider saleDataProvider + */ + public function testExecute(Invoice $invoice) + { + $order = $this->getMockBuilder(Order::class) + ->setMethods(['prepareInvoice', 'addRelatedObject', 'setStatus']) + ->disableOriginalConstructor() + ->getMock(); + $order->expects($this->once()) + ->method('prepareInvoice') + ->willReturn($invoice); + $order->expects($this->once()) + ->method('addRelatedObject'); + $order->expects($this->once()) + ->method('setStatus') + ->with(Order::STATUS_FRAUD); + + /** @var MethodInterface|\PHPUnit_Framework_MockObject_MockObject $paymentMethod */ + $paymentMethod = $this->getMockForAbstractClass(MethodInterface::class); + + /** @var Payment|\PHPUnit_Framework_MockObject_MockObject $orderPayment| */ + $orderPayment = $this->getMockBuilder(Payment::class) + ->setMethods(['setCreatedInvoice', 'getOrder', 'getMethodInstance', 'getIsFraudDetected']) + ->disableOriginalConstructor() + ->getMock(); + $orderPayment->expects($this->once()) + ->method('setCreatedInvoice') + ->with($invoice); + $orderPayment->method('getIsFraudDetected') + ->willReturn(true); + $orderPayment->method('getOrder') + ->willReturn($order); + $orderPayment->method('getMethodInstance') + ->willReturn($paymentMethod); + + $this->assertInstanceOf( + Payment::class, + $this->model->execute($orderPayment) + ); + } + + /** + * @return array + */ + public function saleDataProvider() + { + return [ + ['paid invoice' => $this->getPaidInvoice()], + ['unpaid invoice' => $this->getUnpaidInvoice()] + ]; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getPaidInvoice(): \PHPUnit_Framework_MockObject_MockObject + { + $invoice = $this->getMockBuilder(Invoice::class) + ->setMethods(['register', 'getIsPaid', 'pay']) + ->disableOriginalConstructor() + ->getMock(); + $invoice->expects($this->once()) + ->method('register'); + $invoice->method('getIsPaid') + ->willReturn(true); + $invoice->expects($this->once()) + ->method('pay'); + + return $invoice; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getUnpaidInvoice(): \PHPUnit_Framework_MockObject_MockObject + { + $invoice = $this->getMockBuilder(Invoice::class) + ->setMethods(['register', 'getIsPaid', 'pay']) + ->disableOriginalConstructor() + ->getMock(); + $invoice->expects($this->once()) + ->method('register'); + $invoice->method('getIsPaid') + ->willReturn(false); + $invoice->expects($this->never()) + ->method('pay'); + + return $invoice; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 9d0f10a30e6ef..d27c9619cff9e 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -9,18 +9,19 @@ use Magento\Framework\Model\Context; use Magento\Payment\Helper\Data; use Magento\Payment\Model\Method\AbstractMethod; +use Magento\Payment\Model\Method\Adapter; use Magento\Sales\Api\CreditmemoManagementInterface; +use Magento\Sales\Api\Data\OrderStatusHistoryInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Creditmemo; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Order\OrderStateResolverInterface; use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Operations\SaleOperation; use Magento\Sales\Model\Order\Payment\Transaction; -use PHPUnit_Framework_MockObject_MockObject as MockObject; +use PHPUnit\Framework\MockObject\MockObject; /** - * Class PaymentTest - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) */ @@ -49,17 +50,17 @@ class PaymentTest extends \PHPUnit\Framework\TestCase private $helper; /** - * @var \Magento\Framework\Event\Manager | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\Manager|MockObject */ protected $eventManagerMock; /** - * @var \Magento\Directory\Model\PriceCurrency | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Directory\Model\PriceCurrency|MockObject */ protected $priceCurrencyMock; /** - * @var \Magento\Directory\Model\Currency | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Directory\Model\Currency|MockObject */ protected $currencyMock; @@ -84,51 +85,56 @@ class PaymentTest extends \PHPUnit\Framework\TestCase private $transactionId; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $transactionCollectionFactory; /** - * @var \Magento\Sales\Model\Order\CreditmemoFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\CreditmemoFactory|MockObject */ protected $creditmemoFactoryMock; /** - * @var \Magento\Sales\Model\Order\Creditmemo | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Creditmemo|MockObject */ protected $creditMemoMock; /** - * @var \Magento\Sales\Model\Order\Payment\Transaction\Repository | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Transaction\Repository|MockObject */ protected $transactionRepositoryMock; /** - * @var \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface| \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface|MockObject */ protected $transactionManagerMock; /** - * @var \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface|MockObject */ protected $transactionBuilderMock; /** - * @var \Magento\Sales\Model\Order\Payment\Processor|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Processor|MockObject */ protected $paymentProcessor; /** - * @var \Magento\Sales\Model\OrderRepository|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\OrderRepository|MockObject */ protected $orderRepository; /** - * @var CreditmemoManagementInterface + * @var CreditmemoManagementInterface|MockObject */ private $creditmemoManagerMock; + /** + * @var SaleOperation|MockObject + */ + private $saleOperation; + /** * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -140,6 +146,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->saleOperation = $this->getMockBuilder(SaleOperation::class) + ->disableOriginalConstructor() + ->getMock(); + $this->context = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->getMock(); @@ -177,28 +187,8 @@ function ($value) { } ); - $this->paymentMethod = $this->getMockBuilder(AbstractMethod::class) + $this->paymentMethod = $this->getMockBuilder(Adapter::class) ->disableOriginalConstructor() - ->setMethods( - [ - 'canVoid', - 'authorize', - 'getConfigData', - 'getConfigPaymentAction', - 'validate', - 'setStore', - 'acceptPayment', - 'denyPayment', - 'fetchTransactionInfo', - 'canCapture', - 'canRefund', - 'canOrder', - 'order', - 'isInitializeNeeded', - 'initialize', - 'refund' - ] - ) ->getMock(); $this->invoice = $this->getMockBuilder(Invoice::class) @@ -377,7 +367,7 @@ public function testPlaceActionOrder() ->willReturnSelf(); $this->mockPlaceEvents(); $statusHistory = $this->getMockForAbstractClass( - \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class + OrderStatusHistoryInterface::class ); $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->order->expects($this->any()) @@ -437,7 +427,7 @@ public function testPlaceActionAuthorizeInitializeNeeded() ->willReturnSelf(); $this->mockPlaceEvents(); $statusHistory = $this->getMockForAbstractClass( - \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class + OrderStatusHistoryInterface::class ); $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->order->expects($this->any()) @@ -473,7 +463,7 @@ public function testPlaceActionAuthorizeFraud() ->with('order_status', null) ->willReturn($newOrderStatus); $statusHistory = $this->getMockForAbstractClass( - \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class + OrderStatusHistoryInterface::class ); $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->order->expects($this->any()) @@ -519,7 +509,7 @@ public function testPlaceActionAuthorizeCapture() ->with('order_status', null) ->willReturn($newOrderStatus); $statusHistory = $this->getMockForAbstractClass( - \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class + OrderStatusHistoryInterface::class ); $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->order->expects($this->any()) @@ -545,6 +535,52 @@ public function testPlaceActionAuthorizeCapture() $this->assertEquals($sum, $this->payment->getBaseAmountAuthorized()); } + /** + * Tests place order flow with supported 'sale' payment operation. + */ + public function testPlaceWithSaleOperationSupported() + { + $newOrderStatus = 'new_status'; + $customerNote = 'blabla'; + $sum = 10; + + $this->paymentMethod->method('canSale') + ->willReturn(true); + $this->order->method('getTotalDue') + ->willReturn($sum); + $this->order->method('getBaseTotalDue') + ->willReturn($sum); + $this->helper->method('getMethodInstance') + ->willReturn($this->paymentMethod); + $this->paymentMethod->method('getConfigPaymentAction') + ->willReturn(AbstractMethod::ACTION_AUTHORIZE_CAPTURE); + $this->paymentMethod->method('getConfigData') + ->with('order_status', null) + ->willReturn($newOrderStatus); + $statusHistory = $this->getMockForAbstractClass(OrderStatusHistoryInterface::class); + $this->order->method('getCustomerNote') + ->willReturn($customerNote); + $this->order->method('addStatusHistoryComment') + ->with($customerNote) + ->willReturn($statusHistory); + $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $newOrderStatus, ['first', 'second']); + $this->order->method('setState') + ->with(Order::STATE_PROCESSING) + ->willReturnSelf(); + $this->order->method('setStatus') + ->with($newOrderStatus) + ->willReturnSelf(); + $this->paymentMethod->expects($this->once()) + ->method('getConfigPaymentAction') + ->willReturn(null); + $this->saleOperation->expects($this->once()) + ->method('execute'); + + $this->assertEquals($this->payment, $this->payment->place()); + $this->assertEquals($sum, $this->payment->getAmountAuthorized()); + $this->assertEquals($sum, $this->payment->getBaseAmountAuthorized()); + } + /** * @param bool $isOnline * @param float $amount @@ -1594,7 +1630,8 @@ protected function initPayment() 'transactionBuilder' => $this->transactionBuilderMock, 'paymentProcessor' => $this->paymentProcessor, 'orderRepository' => $this->orderRepository, - 'creditmemoManager' => $this->creditmemoManagerMock + 'creditmemoManager' => $this->creditmemoManagerMock, + 'saleOperation' => $this->saleOperation ] ); } @@ -1621,7 +1658,7 @@ protected function assertOrderUpdated( ->willReturnSelf(); $statusHistory = $this->getMockForAbstractClass( - \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class + OrderStatusHistoryInterface::class ); $this->order->expects($this->any()) ->method('addStatusHistoryComment') diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/DataProvider/DocumentTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/DataProvider/DocumentTest.php deleted file mode 100644 index 8052c06eee8d9..0000000000000 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/DataProvider/DocumentTest.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Test\Unit\Ui\Component\DataProvider; - -use Magento\Customer\Api\Data\GroupInterface; -use Magento\Customer\Api\GroupRepositoryInterface; -use Magento\Framework\Api\AttributeValue; -use Magento\Framework\Api\AttributeValueFactory; -use Magento\Sales\Model\Order\Invoice; -use Magento\Sales\Ui\Component\DataProvider\Document; -use PHPUnit_Framework_MockObject_MockObject as MockObject; - -/** - * Class DocumentTest - */ -class DocumentTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var GroupRepositoryInterface|MockObject - */ - private $groupRepository; - - /** - * @var AttributeValueFactory|MockObject - */ - private $attributeValueFactory; - - /** - * @var Document - */ - private $document; - - protected function setUp() - { - $this->initAttributeValueFactoryMock(); - - $this->groupRepository = $this->getMockForAbstractClass(GroupRepositoryInterface::class); - - $this->document = new Document($this->attributeValueFactory, $this->groupRepository); - } - - /** - * @covers \Magento\Sales\Ui\Component\DataProvider\Document::getCustomAttribute - */ - public function testGetStateAttribute() - { - $this->document->setData('state', Invoice::STATE_PAID); - - $this->groupRepository->expects(static::never()) - ->method('getById'); - - $attribute = $this->document->getCustomAttribute('state'); - static::assertEquals('Paid', $attribute->getValue()); - } - - /** - * @covers \Magento\Sales\Ui\Component\DataProvider\Document::getCustomAttribute - */ - public function testGetCustomerGroupAttribute() - { - $this->document->setData('customer_group_id', 1); - - $group = $this->getMockForAbstractClass(GroupInterface::class); - - $this->groupRepository->expects(static::once()) - ->method('getById') - ->willReturn($group); - - $group->expects(static::once()) - ->method('getCode') - ->willReturn('General'); - - $attribute = $this->document->getCustomAttribute('customer_group_id'); - static::assertEquals('General', $attribute->getValue()); - } - - /** - * Create mock for attribute value factory - * @return void - */ - private function initAttributeValueFactoryMock() - { - $this->attributeValueFactory = $this->getMockBuilder(AttributeValueFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - - $attributeValue = new AttributeValue(); - - $this->attributeValueFactory->expects(static::once()) - ->method('create') - ->willReturn($attributeValue); - } -} diff --git a/app/code/Magento/Sales/Ui/Component/DataProvider/Document.php b/app/code/Magento/Sales/Ui/Component/DataProvider/Document.php deleted file mode 100644 index 3030a16cc18b9..0000000000000 --- a/app/code/Magento/Sales/Ui/Component/DataProvider/Document.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Sales\Ui\Component\DataProvider; - -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Sales\Model\Order\Invoice; -use Magento\Customer\Api\GroupRepositoryInterface; -use Magento\Framework\Api\AttributeValueFactory; - -/** - * Class Document - */ -class Document extends \Magento\Framework\View\Element\UiComponent\DataProvider\Document -{ - /** - * @var string - */ - private static $stateAttributeCode = 'state'; - - /** - * @var string - */ - private static $customerGroupAttributeCode = 'customer_group_id'; - - /** - * @var GroupRepositoryInterface - */ - private $groupRepository; - - /** - * Document constructor. - * @param AttributeValueFactory $attributeValueFactory - * @param GroupRepositoryInterface $groupRepository - */ - public function __construct( - AttributeValueFactory $attributeValueFactory, - GroupRepositoryInterface $groupRepository - ) { - parent::__construct($attributeValueFactory); - $this->groupRepository = $groupRepository; - } - - /** - * @inheritdoc - */ - public function getCustomAttribute($attributeCode) - { - switch ($attributeCode) { - case self::$stateAttributeCode: - $this->setStateValue(); - break; - case self::$customerGroupAttributeCode: - $this->setCustomerGroupValue(); - break; - } - return parent::getCustomAttribute($attributeCode); - } - - /** - * Update invoice state value - * Method set text label instead id value - * @return void - */ - private function setStateValue() - { - $value = $this->getData(self::$stateAttributeCode); - /** @var \Magento\Framework\Phrase $state */ - $state = Invoice::getStates()[$value]; - - $this->setCustomAttribute(self::$stateAttributeCode, $state->getText()); - } - - /** - * Update customer group value - * Method set group code instead id value - * @return void - */ - private function setCustomerGroupValue() - { - $value = $this->getData(self::$customerGroupAttributeCode); - try { - $group = $this->groupRepository->getById($value); - $this->setCustomAttribute(self::$customerGroupAttributeCode, $group->getCode()); - } catch (NoSuchEntityException $e) { - $this->setCustomAttribute(self::$customerGroupAttributeCode, 'N/A'); - } - } -} diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 1c84482678f62..b4dadfa944a5b 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -832,6 +832,12 @@ </argument> </arguments> </type> + <virtualType name="Magento\Sales\Model\ResourceModel\Order\Invoice\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> + <arguments> + <argument name="mainTable" xsi:type="string">sales_invoice_grid</argument> + <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Invoice</argument> + </arguments> + </virtualType> <type name="Magento\Sales\Model\Order\Config"> <arguments> <argument name="state" xsi:type="object">Magento\Framework\App\State\Proxy</argument> @@ -935,6 +941,11 @@ <argument name="stateCommand" xsi:type="object">Magento\Sales\Model\Order\Payment\State\CaptureCommand</argument> </arguments> </type> + <type name="Magento\Sales\Model\Order\Payment\Operations\ProcessInvoiceOperation"> + <arguments> + <argument name="stateCommand" xsi:type="object">Magento\Sales\Model\Order\Payment\State\CaptureCommand</argument> + </arguments> + </type> <type name="Magento\Sales\Model\Order\Payment\Operations\OrderOperation"> <arguments> <argument name="stateCommand" xsi:type="object">Magento\Sales\Model\Order\Payment\State\OrderCommand</argument> diff --git a/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml b/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml index 80a0ea02499cc..3e2b653e8b3bd 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/order_date.phtml @@ -5,5 +5,11 @@ */ ?> <div class="order-date"> - <?= $block->escapeHtml(__('<span class="label">Order Date:</span> %1', '<date>' . $block->formatDate($block->getOrder()->getCreatedAt(), \IntlDateFormatter::LONG) . '</date>'), ['span', 'date']) ?> + <?= $block->escapeHtml( + __( + '<span class="label">Order Date:</span> %1', + '<span>' . $block->formatDate($block->getOrder()->getCreatedAt(), \IntlDateFormatter::LONG) . '</span>' + ), + ['span'] + )?> </div> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml index fadfadc8ee7cd..c8363a3df6221 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml @@ -15,8 +15,7 @@ <click selector="{{DiscountSection.DiscountTab}}" stepKey="clickToAddDiscount"/> <fillField selector="{{DiscountSection.DiscountInput}}" userInput="{{discountCode}}" stepKey="fillFieldDiscountCode"/> <click selector="{{DiscountSection.ApplyCodeBtn}}" stepKey="clickToApplyDiscount"/> - <waitForElement selector="{{DiscountSection.DiscountVerificationMsg}}" time="30" stepKey="waitForDiscountToBeAdded"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingFinished"/> + <waitForElementVisible selector="{{DiscountSection.DiscountVerificationMsg}}" time="30" stepKey="waitForDiscountToBeAdded"/> <see selector="{{DiscountSection.DiscountVerificationMsg}}" userInput="Your coupon was successfully applied" stepKey="assertDiscountApplyMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Section/DiscountSection.xml b/app/code/Magento/SalesRule/Test/Mftf/Section/DiscountSection.xml index 45dce325f3cb8..90b591a7bb1b1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Section/DiscountSection.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Section/DiscountSection.xml @@ -13,7 +13,7 @@ <element name="DiscountInput" type="input" selector="#discount-code"/> <element name="ApplyCodeBtn" type="button" selector="//span[text()='Apply Discount']"/> <element name="CancelCoupon" type="button" selector="//button[@value='Cancel Coupon']"/> - <element name="DiscountVerificationMsg" type="button" selector=".message-success div"/> + <element name="DiscountVerificationMsg" type="text" selector=".message-success div"/> <element name="CancelCouponBtn" type="button" selector="#discount-form .action-cancel"/> </section> </sections> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCartRulesAppliedForProductInCartTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCartRulesAppliedForProductInCartTest.xml index 916416dcd9141..49dcc47e14779 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCartRulesAppliedForProductInCartTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCartRulesAppliedForProductInCartTest.xml @@ -46,7 +46,7 @@ </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilters1"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Start creating a bundle product--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateBuyXGetYFreeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateBuyXGetYFreeTest.xml index addb65a68fad3..3f063b5869129 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateBuyXGetYFreeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateBuyXGetYFreeTest.xml @@ -30,7 +30,7 @@ <argument name="ruleName" value="{{_defaultCoupon.code}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a cart price rule of type Buy X get Y free --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml index 0d23e0e035432..54a6f7a16bb23 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml @@ -27,7 +27,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> <argument name="ruleName" value="{{CartPriceRuleConditionAndFreeShippingApplied.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml index b41e139536223..0e1a4d7c186aa 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionIsNotAppliedTest.xml @@ -29,7 +29,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> <argument name="ruleName" value="{{CartPriceRuleConditionNotApplied.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logoutAsAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutAsAdmin"/> </after> <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml index f0075a92a2b82..64443c717ac33 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml @@ -34,7 +34,7 @@ </actionGroup> <deleteData createDataKey="category" stepKey="deleteCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Set timezone--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml index 6242c1f3d1baf..f33eb187e4cc8 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml @@ -30,7 +30,7 @@ <argument name="ruleName" value="{{_defaultCoupon.code}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create a cart price rule based on a coupon code --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml index 78943a0648b51..4b793dbf8583f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml @@ -30,7 +30,7 @@ <argument name="ruleName" value="{{_defaultCoupon.code}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a cart price rule --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml index 385c9e35da393..7365f3b7a3425 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -27,7 +27,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForSubtotal.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml index a56e332ce1a85..81c30d197759d 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -34,7 +34,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForCategory.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml index 0541ee2dd4eba..2685e004ba1e0 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml @@ -27,7 +27,7 @@ <actionGroup ref="DeleteCartPriceRuleByName" stepKey="deleteCreatedCartPriceRule"> <argument name="ruleName" value="{{CartPriceRuleConditionAppliedForWeight.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create cart price rule as per data and verify AssertCartPriceRuleSuccessSaveMessage--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountDiscountTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountDiscountTest.xml index c65a5a865e779..f6d61f62c1f54 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountDiscountTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountDiscountTest.xml @@ -30,7 +30,7 @@ <argument name="ruleName" value="{{_defaultCoupon.code}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a cart price rule for $10 Fixed amount discount --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml index 69ba7aef393b5..cb3e6c517e1ec 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateFixedAmountWholeCartDiscountTest.xml @@ -30,7 +30,7 @@ <argument name="ruleName" value="{{SimpleSalesRule.name}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a cart price rule for Fixed amount discount for whole cart --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateInvalidRuleTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateInvalidRuleTest.xml index 620112e323ff5..3bbacf912e5d6 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateInvalidRuleTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateInvalidRuleTest.xml @@ -23,7 +23,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceList"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreatePercentOfProductPriceTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreatePercentOfProductPriceTest.xml index fd3ebd2ad11d7..38986dc32f8d2 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreatePercentOfProductPriceTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreatePercentOfProductPriceTest.xml @@ -21,6 +21,8 @@ <before> <createData entity="_defaultCategory" stepKey="createPreReqCategory"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> @@ -30,7 +32,7 @@ <argument name="ruleName" value="{{_defaultCoupon.code}}"/> </actionGroup> <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a cart price rule for 50 percent of product price --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml index 9a71210aac1c6..aed9d71c306ae 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithComplexConditionsAndVerifyDeleteMessageTest.xml @@ -62,7 +62,7 @@ <actionGroup ref="AssertCartPriceRuleSuccessSaveMessageActionGroup" stepKey="assertVerifyCartPriceRuleSuccessSaveMessage"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete active cart price rule--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml index 34b8363e8b5ce..fc9a92765c2d0 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteActiveSalesRuleWithPercentPriceAndVerifyDeleteMessageTest.xml @@ -28,7 +28,7 @@ </actionGroup> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete active cart price rule--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml index 39a5d0f6a7131..6de5f127a296c 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminDeleteInactiveSalesRuleAndVerifyDeleteMessageTest.xml @@ -30,7 +30,7 @@ </before> <after> <deleteData createDataKey="initialSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete inactive cart price rule--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminMarketingCartPriceRulesNavigateMenuTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminMarketingCartPriceRulesNavigateMenuTest.xml index f281b0abf87a0..58d7ea7c1bad8 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminMarketingCartPriceRulesNavigateMenuTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminMarketingCartPriceRulesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToMarketingCartPriceRulesPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index ec9246f7c33bd..41062b8153b3f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -74,6 +74,9 @@ <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> @@ -86,7 +89,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Create the rule --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml index 84537fb69ed41..60ece859dde96 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontAutoGeneratedCouponCodeTest.xml @@ -34,7 +34,7 @@ <deleteData createDataKey="createSalesRule" stepKey="deleteSalesRule"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login as Admin --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantity.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantity.xml index ad060c1412c8c..08a7bd72cd18d 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantity.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantity.xml @@ -24,6 +24,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> @@ -61,7 +62,8 @@ <fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="1.00" stepKey="fillDiscountAmount"/> <click selector="{{AdminCartPriceRulesFormSection.save}}" stepKey="clickSaveButton"/> <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + <!-- Add 1 product to the cart --> <amOnPage url="$$createPreReqProduct.name$$.html" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotal.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotal.xml index 510bfabf303f5..94e53cfc88047 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotal.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotal.xml @@ -24,6 +24,7 @@ <createData entity="_defaultProduct" stepKey="createPreReqProduct"> <requiredEntity createDataKey="createPreReqCategory"/> </createData> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartRuleCouponForFreeShippingTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartRuleCouponForFreeShippingTest.xml index 3526ab20aa6b4..12c278d1e7b63 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartRuleCouponForFreeShippingTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartRuleCouponForFreeShippingTest.xml @@ -39,7 +39,7 @@ <deleteData createDataKey="createCartPriceRule" stepKey="deleteSalesRule"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logoutFromBackend"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromBackend"/> </after> <!-- Login with created Customer --> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml index f12b8ea7ca331..80b0747a3bf72 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml @@ -92,7 +92,7 @@ <magentoCLI command="config:set tax/cart_display/subtotal 1" stepKey="unsetSubtotal"/> <magentoCLI command="config:set carriers/freeshipping/active 0" stepKey="unsetFreeShipping"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Add testing products to the cart --> <amOnPage url="{{StorefrontProductPage.url($$createSimpleProductFirst.custom_attributes[url_key]$$)}}" stepKey="goToProductPage"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToComplexProductsTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToComplexProductsTest.xml index dbeb4ba94061b..b43fd095b5556 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToComplexProductsTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToComplexProductsTest.xml @@ -72,7 +72,7 @@ <deleteData createDataKey="createConfigProductAttributeCreateConfigurableProduct2" stepKey="deleteConfigProductAttribute2"/> <!--Delete Cart Price Rule --> <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1: Create a cart price rule applying to CAT1 with discount --> <createData entity="SalesRuleNoCouponWithFixedDiscount" stepKey="createCartPriceRule"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToGroupedProductWithInvisibleIndividualProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToGroupedProductWithInvisibleIndividualProductTest.xml index 13b2661dcb9d0..13c1100bd21f6 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToGroupedProductWithInvisibleIndividualProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCategoryRulesShouldApplyToGroupedProductWithInvisibleIndividualProductTest.xml @@ -14,7 +14,7 @@ <title value="Category rules should apply to grouped product with invisible individual products"/> <description value="Category rules should apply to grouped product with invisible individual products"/> <severity value="CRITICAL"/> - <testCaseId value="MC-13608"/> + <testCaseId value="MC-31863"/> <group value="SalesRule"/> </annotations> <before> @@ -77,7 +77,7 @@ <argument name="ruleName" value="TestSalesRule"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Start to create new cart price rule via Category conditions --> <actionGroup ref="AdminCreateCartPriceRuleWithConditionIsCategoryActionGroup" stepKey="createCartPriceRuleWithCondition"> diff --git a/app/code/Magento/SalesRule/Test/Unit/Observer/AssignCouponDataAfterOrderCustomerAssignObserverTest.php b/app/code/Magento/SalesRule/Test/Unit/Observer/AssignCouponDataAfterOrderCustomerAssignObserverTest.php new file mode 100644 index 0000000000000..f72a47a318de0 --- /dev/null +++ b/app/code/Magento/SalesRule/Test/Unit/Observer/AssignCouponDataAfterOrderCustomerAssignObserverTest.php @@ -0,0 +1,150 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\SalesRule\Test\Unit\Observer; + +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\SalesRule\Model\Coupon\UpdateCouponUsages; +use Magento\SalesRule\Observer\AssignCouponDataAfterOrderCustomerAssignObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for Magento\SalesRule\Observer\AssignCouponDataAfterOrderCustomerAssignObserver + */ +class AssignCouponDataAfterOrderCustomerAssignObserverTest extends TestCase +{ + /* + * Stub event key order + */ + private const STUB_EVENT_KEY_ORDER = 'order'; + + /* + * Stub customer ID + */ + private const STUB_CUSTOMER_ID = 1; + + /** + * Testable Object + * + * @var AssignCouponDataAfterOrderCustomerAssignObserver + */ + private $observer; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * @var OrderInterface|MockObject + */ + private $orderMock; + + /** + * @var UpdateCouponUsages|MockObject + */ + private $updateCouponUsagesMock; + + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getData']) + ->getMock(); + + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->updateCouponUsagesMock = $this->getMockBuilder(UpdateCouponUsages::class) + ->disableOriginalConstructor() + ->setMethods(['execute']) + ->getMock(); + + $this->observer = $this->objectManager->getObject( + AssignCouponDataAfterOrderCustomerAssignObserver::class, + [ + 'updateCouponUsages' => $this->updateCouponUsagesMock + ] + ); + } + + /** + * Test for execute(), covers test case for assign coupon data after order customer + */ + public function testExecuteAssignCouponData(): void + { + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getData') + ->with(self::STUB_EVENT_KEY_ORDER) + ->willReturn($this->orderMock); + + $this->orderMock + ->expects($this->once()) + ->method('getCustomerId') + ->willReturn(self::STUB_CUSTOMER_ID); + + $this->updateCouponUsagesMock + ->expects($this->once()) + ->method('execute') + ->with($this->orderMock, true); + + $this->observer->execute($this->observerMock); + } + + /** + * Test for execute(), covers test case for assign coupon data after order customer with empty customer ID + */ + public function testExecuteAssignCouponDataWithEmptyCustomerId(): void + { + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getData') + ->with(self::STUB_EVENT_KEY_ORDER) + ->willReturn($this->orderMock); + + $this->orderMock + ->expects($this->once()) + ->method('getCustomerId') + ->willReturn(null); + + $this->updateCouponUsagesMock + ->expects($this->never()) + ->method('execute'); + + $this->observer->execute($this->observerMock); + } +} diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php index 7a4aabea85680..8422123c0ca84 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php @@ -132,6 +132,7 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) || $object->getData('store_id') === null || !$object->getData('sequence_table') ) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception(__('Not enough arguments')); } diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php new file mode 100644 index 0000000000000..e86cc8b1b2e6d --- /dev/null +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\SalesSequence\Model\Sequence; + +use Magento\Framework\App\ResourceConnection as AppResource; +use Magento\SalesSequence\Model\MetaFactory; +use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; + +/** + * Delete Sequence by Store. + */ +class DeleteByStore +{ + /** + * @var ResourceMetadata + */ + private $resourceMetadata; + + /** + * @var MetaFactory + */ + private $metaFactory; + + /** + * @var AppResource + */ + private $appResource; + + /** + * @param ResourceMetadata $resourceMetadata + * @param MetaFactory $metaFactory + * @param AppResource $appResource + */ + public function __construct( + ResourceMetadata $resourceMetadata, + MetaFactory $metaFactory, + AppResource $appResource + ) { + $this->resourceMetadata = $resourceMetadata; + $this->metaFactory = $metaFactory; + $this->appResource = $appResource; + } + + /** + * Deletes all sequence linked entites + * + * @param int $storeId + * @return void + * @throws \Exception + */ + public function execute($storeId): void + { + $metadataIds = $this->getMetadataIdsByStoreId($storeId); + $profileIds = $this->getProfileIdsByMetadataIds($metadataIds); + + $this->appResource->getConnection()->delete( + $this->appResource->getTableName('sales_sequence_profile'), + ['profile_id IN (?)' => $profileIds] + ); + + foreach ($metadataIds as $metadataId) { + $metadata = $this->metaFactory->create(); + $this->resourceMetadata->load($metadata, $metadataId); + if (!$metadata->getId()) { + continue; + } + + $this->appResource->getConnection()->dropTable( + $metadata->getSequenceTable() + ); + $this->resourceMetadata->delete($metadata); + } + } + + /** + * Retrieves Metadata Ids by store id + * + * @param int $storeId + * @return int[] + */ + private function getMetadataIdsByStoreId($storeId) + { + $connection = $this->appResource->getConnection(); + $bind = ['store_id' => $storeId]; + $select = $connection->select()->from( + $this->appResource->getTableName('sales_sequence_meta'), + ['meta_id'] + )->where( + 'store_id = :store_id' + ); + + return $connection->fetchCol($select, $bind); + } + + /** + * Retrieves Profile Ids by metadata ids + * + * @param int[] $metadataIds + * @return int[] + */ + private function getProfileIdsByMetadataIds(array $metadataIds) + { + $connection = $this->appResource->getConnection(); + $select = $connection->select() + ->from( + $this->appResource->getTableName('sales_sequence_profile'), + ['profile_id'] + )->where('meta_id IN (?)', $metadataIds); + + return $connection->fetchCol($select); + } +} diff --git a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php new file mode 100644 index 0000000000000..c10ef80f6eb9b --- /dev/null +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\SalesSequence\Observer; + +use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Event\Observer as EventObserver; +use Magento\SalesSequence\Model\Sequence\DeleteByStore; + +/** + * Observer for Sequence Removal. + */ +class SequenceRemovalObserver implements ObserverInterface +{ + /** + * @var DeleteByStore + */ + private $deleteByStore; + + /** + * @param DeleteByStore $deleteByStore + */ + public function __construct( + DeleteByStore $deleteByStore + ) { + $this->deleteByStore = $deleteByStore; + } + + /** + * Deletes all sequence linked entities. + * + * @param EventObserver $observer + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function execute(EventObserver $observer) + { + if ($store = $observer->getData('store')) { + $this->deleteByStore->execute($store->getId()); + } + + return $this; + } +} diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php new file mode 100644 index 0000000000000..17dbd6c37265f --- /dev/null +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\SalesSequence\Test\Unit\Model\Sequence; + +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Select; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\SalesSequence\Model\Meta; +use Magento\SalesSequence\Model\MetaFactory; +use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMeta; +use Magento\SalesSequence\Model\Sequence\DeleteByStore; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test for \Magento\SalesSequence\Model\Sequence\DeleteByStore class. + */ +class DeleteByStoreTest extends TestCase +{ + /** + * @var DeleteByStore + */ + private $deleteByStore; + + /** + * @var ResourceMeta | MockObject + */ + private $resourceSequenceMeta; + + /** + * @var Meta | MockObject + */ + private $meta; + + /** + * @var MetaFactory | MockObject + */ + private $metaFactory; + + /** + * @var AdapterInterface | MockObject + */ + private $connectionMock; + + /** + * @var ResourceConnection | MockObject + */ + private $resourceMock; + + /** + * @var Select | MockObject + */ + private $select; + + protected function setUp() + { + $this->connectionMock = $this->getMockForAbstractClass( + AdapterInterface::class, + [], + '', + false, + false, + true, + ['delete', 'query'] + ); + $this->resourceSequenceMeta = $this->createPartialMock( + ResourceMeta::class, + ['load', 'delete'] + ); + $this->meta = $this->createPartialMock( + Meta::class, + ['getSequenceTable'] + ); + $this->resourceMock = $this->createMock(ResourceConnection::class); + $this->select = $this->createMock(Select::class); + $this->metaFactory = $this->createPartialMock(MetaFactory::class, ['create']); + $this->metaFactory->method('create')->willReturn($this->meta); + + $helper = new ObjectManager($this); + $this->deleteByStore = $helper->getObject( + DeleteByStore::class, + [ + 'resourceMetadata' => $this->resourceSequenceMeta, + 'metaFactory' => $this->metaFactory, + 'appResource' => $this->resourceMock, + ] + ); + } + + /** + * @throws \Exception + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testExecute() + { + $profileTableName = 'sales_sequence_profile'; + $storeId = 1; + $metadataIds = [1, 2]; + $profileIds = [10, 11]; + $this->resourceMock->method('getTableName') + ->willReturnCallback( + static function ($tableName) { + return $tableName; + } + ); + $this->resourceMock->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock + ->method('select') + ->willReturn($this->select); + + $this->select->method('from') + ->willReturn($this->select); + $this->select->method('where') + ->willReturn($this->select); + + $this->connectionMock->method('fetchCol') + ->willReturnCallback( + static function ($arg, $arg2) use ($metadataIds, $profileIds) { + if (array_key_exists('store', $arg2)) { + return $metadataIds; + } + + return $profileIds; + } + ); + + $this->connectionMock->expects($this->once()) + ->method('delete') + ->with($profileTableName, ['profile_id IN (?)' => $profileIds]) + ->willReturn(2); + $this->resourceSequenceMeta + ->method('load') + ->willReturn($this->meta); + $this->connectionMock + ->method('dropTable') + ->willReturn(true); + $this->resourceSequenceMeta + ->method('delete') + ->willReturn($this->resourceSequenceMeta); + $this->deleteByStore->execute($storeId); + } +} diff --git a/app/code/Magento/SalesSequence/etc/events.xml b/app/code/Magento/SalesSequence/etc/events.xml new file mode 100644 index 0000000000000..5bbde6ab188a5 --- /dev/null +++ b/app/code/Magento/SalesSequence/etc/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="store_delete"> + <observer name="magento_sequence" instance="Magento\SalesSequence\Observer\SequenceRemovalObserver" /> + </event> +</config> diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index b27ef6b01fda2..ed6a2c5215b54 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -9,6 +9,8 @@ */ namespace Magento\Search\Block; +use Magento\Framework\DataObject; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\UrlFactory; use Magento\Framework\UrlInterface; use Magento\Framework\View\Element\Template; @@ -16,6 +18,8 @@ use Magento\Search\Model\ResourceModel\Query\CollectionFactory; /** + * Terms and conditions block + * * @api * @since 100.0.2 */ @@ -37,15 +41,11 @@ class Term extends Template protected $_maxPopularity; /** - * Url factory - * * @var UrlFactory */ protected $_urlFactory; /** - * Query collection factory - * * @var CollectionFactory */ protected $_queryCollectionFactory; @@ -71,17 +71,17 @@ public function __construct( * Load terms and try to sort it by names * * @return $this - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ protected function _loadTerms() { if (empty($this->_terms)) { $this->_terms = []; - $terms = $this->_queryCollectionFactory->create()->setPopularQueryFilter( - $this->_storeManager->getStore()->getId() - )->setPageSize( - 100 - )->load()->getItems(); + $terms = $this->_queryCollectionFactory->create() + ->setPopularQueryFilter($this->_storeManager->getStore()->getId()) + ->setPageSize(100) + ->load() + ->getItems(); if (count($terms) == 0) { return $this; @@ -91,6 +91,7 @@ protected function _loadTerms() $this->_minPopularity = end($terms)->getPopularity(); $range = $this->_maxPopularity - $this->_minPopularity; $range = $range == 0 ? 1 : $range; + $termKeys = []; foreach ($terms as $term) { if (!$term->getPopularity()) { continue; @@ -99,6 +100,7 @@ protected function _loadTerms() $temp[$term->getQueryText()] = $term; $termKeys[] = $term->getQueryText(); } + natcasesort($termKeys); foreach ($termKeys as $termKey) { @@ -109,8 +111,10 @@ protected function _loadTerms() } /** + * Load and return terms + * * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ public function getTerms() { @@ -119,7 +123,9 @@ public function getTerms() } /** - * @param \Magento\Framework\DataObject $obj + * Return search url + * + * @param DataObject $obj * @return string */ public function getSearchUrl($obj) @@ -135,6 +141,8 @@ public function getSearchUrl($obj) } /** + * Return max popularity + * * @return int */ public function getMaxPopularity() @@ -143,6 +151,8 @@ public function getMaxPopularity() } /** + * Return min popularity + * * @return int */ public function getMinPopularity() diff --git a/app/code/Magento/Search/Test/Mftf/Test/AdminGlobalSearchOnProductPageTest.xml b/app/code/Magento/Search/Test/Mftf/Test/AdminGlobalSearchOnProductPageTest.xml index 725f45c0bc6e3..6ff7a34a03b8a 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/AdminGlobalSearchOnProductPageTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/AdminGlobalSearchOnProductPageTest.xml @@ -34,7 +34,7 @@ </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create Simple Product --> diff --git a/app/code/Magento/Search/Test/Mftf/Test/AdminMassDeleteSearchTermEntityTest.xml b/app/code/Magento/Search/Test/Mftf/Test/AdminMassDeleteSearchTermEntityTest.xml index 01c361d336541..2b7a4e7f5e5cb 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/AdminMassDeleteSearchTermEntityTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/AdminMassDeleteSearchTermEntityTest.xml @@ -30,7 +30,7 @@ </before> <after> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to the catalog search term page --> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontUsingElasticSearchWithWeightAttributeTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontUsingElasticSearchWithWeightAttributeTest.xml new file mode 100644 index 0000000000000..504dee5067187 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontUsingElasticSearchWithWeightAttributeTest.xml @@ -0,0 +1,61 @@ +<?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="StorefrontUsingElasticSearchWithWeightAttributeTest"> + <annotations> + <features value="CatalogSearch"/> + <stories value="Storefront Search"/> + <title value="Using ElasticSearch with weight attribute"/> + <description value="Use ElasticSearch for products with weight attributes"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-31743"/> + <group value="SearchEngineElasticsearch"/> + </annotations> + <before> + <!--Create Simple Product with weight--> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Delete create product --> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <!-- Change attribute property: Use in Search >No --> + <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openWeightProductAttributeInAdmin"> + <argument name="productAttributeCode" value="weight"/> + </actionGroup> + <actionGroup ref="AdminSetUseInSearchValueForProductAttributeActionGroup" stepKey="makeAttributeUnsearchableInAQuickSearch"> + <argument name="useInSearchValue" value="No"/> + </actionGroup> + <actionGroup ref="SaveProductAttributeActionGroup" stepKey="saveAttributeChanges"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> + <!-- Logout from admin --> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + <!-- Step 2 --> + <actionGroup ref="OpenProductAttributeFromSearchResultInGridActionGroup" stepKey="openWeightProductAttribute"> + <argument name="productAttributeCode" value="weight"/> + </actionGroup> + <!-- Change attribute property: Use in Search >Yes --> + <actionGroup ref="AdminSetUseInSearchValueForProductAttributeActionGroup" stepKey="makeAttributeSearchableInAQuickSearch"/> + <actionGroup ref="SaveProductAttributeActionGroup" stepKey="saveAttribute"/> + <!-- Step 3 --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + <!-- Step 4 --> + <magentoCLI command="cache:clean" arguments="full_page" stepKey="clearFPC"/> + <!-- Step 5 --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToStorefront"/> + <!-- Step 6 --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByAnyValue"> + <argument name="phrase" value="exampleTestValue2020"/> + </actionGroup> + <see selector="{{StorefrontCatalogSearchMainSection.message}}" userInput="Your search returned no results." stepKey="seeCantFindProductMessage"/> + </test> +</tests> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml index 93a0f98f6f828..5030484434925 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductDescriptionTest.xml @@ -39,7 +39,7 @@ </actionGroup> <!-- Delete created below search terms --> <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to storefront home page --> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml index fc933c90341f9..1d312959a4a00 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductNameTest.xml @@ -43,7 +43,7 @@ </actionGroup> <!-- Delete created below search terms --> <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to storefront home page --> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml index 65472b9e10282..3ae29f60a8e86 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductShortDescriptionTest.xml @@ -45,7 +45,7 @@ <!-- Delete created below search terms --> <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to storefront home page --> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml index 6e80823b78e0f..e14cbbb85a0e7 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByProductSkuTest.xml @@ -45,7 +45,7 @@ <!-- Delete created below search terms --> <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to storefront home page --> diff --git a/app/code/Magento/Search/Test/Unit/Block/TermsTest.php b/app/code/Magento/Search/Test/Unit/Block/TermsTest.php new file mode 100644 index 0000000000000..d2e7e94a65f8e --- /dev/null +++ b/app/code/Magento/Search/Test/Unit/Block/TermsTest.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Test\Unit\Block; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Url; +use Magento\Framework\UrlFactory; +use Magento\Framework\View\Element\Template\Context; +use Magento\Search\Block\Term; +use Magento\Search\Model\Query; +use Magento\Search\Model\ResourceModel\Query\Collection; +use Magento\Search\Model\ResourceModel\Query\CollectionFactory; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManager; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Tests for Terms block + */ +class TermsTest extends TestCase +{ + /** + * @var Context|MockObject + */ + private $contextMock; + + /** + * @var CollectionFactory|MockObject + */ + private $collectionFactoryMock; + + /** + * @var UrlFactory|MockObject + */ + private $urlFactoryMock; + + /** + * @var Term + */ + private $termsModel; + + /** + * @var StoreManager + */ + private $storeManagerMock; + + /** + * @inheritdoc + */ + public function setUp() + { + $objectManager = new ObjectManager($this); + + $this->contextMock = $this->createMock(Context::class); + $this->collectionFactoryMock = $this->createMock(CollectionFactory::class); + $this->urlFactoryMock = $this->createMock(UrlFactory::class); + $this->storeManagerMock = $this->createMock(StoreManager::class); + + $this->contextMock->expects($this->once()) + ->method('getStoreManager') + ->willReturn($this->storeManagerMock); + $this->termsModel = $objectManager->getObject( + Term::class, + [ + 'context' => $this->contextMock, + '_queryCollectionFactory' => $this->collectionFactoryMock, + '_urlFactory' => $this->urlFactoryMock + ] + ); + } + + /** + * Verify terms + * + * @dataProvider termKeysProvider + * @param string $termKey + * @param bool $popularity + */ + public function testGetTerms(string $termKey, bool $popularity): void + { + $terms = $this->createMock(Collection::class); + $dataObjectMock = $this->getMockBuilder(Query::class) + ->disableOriginalConstructor() + ->setMethods(['getPopularity', 'getQueryText']) + ->getMock(); + $storeMock = $this->createMock(Store::class); + + $this->storeManagerMock->expects($this->once()) + ->method('getStore') + ->willReturn($storeMock); + $storeMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + + $this->collectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($terms); + $terms->expects($this->once()) + ->method('setPopularQueryFilter') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('setPageSize') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('load') + ->willReturnSelf(); + $terms->expects($this->once()) + ->method('getItems') + ->willReturn([$dataObjectMock]); + $dataObjectMock->expects($this->exactly(!$popularity ? 3 : 4)) + ->method('getPopularity') + ->willReturn($popularity); + $dataObjectMock->expects($this->exactly(!$popularity ? 0 : 2)) + ->method('getQueryText') + ->willReturn($termKey); + + $this->assertEquals(!$popularity ? [] : [$termKey => $dataObjectMock], $this->termsModel->getTerms()); + } + + /** + * Verify get search Url + * + * @return void + */ + public function testGetSearchResult(): void + { + $urlMock = $this->getMockBuilder(Url::class) + ->disableOriginalConstructor() + ->setMethods(['setQueryParam', 'getUrl']) + ->getMock(); + + $dataObjectMock = $this->getMockBuilder(Query::class) + ->disableOriginalConstructor() + ->setMethods(['getPopularity', 'getQueryText']) + ->getMock(); + $this->urlFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($urlMock); + $dataObjectMock->expects($this->once()) + ->method('getQueryText') + ->willReturn('url'); + $urlMock->expects($this->once())->method('setQueryParam'); + $urlMock->expects($this->once()) + ->method('getUrl') + ->with('catalogsearch/result') + ->willReturn('url'); + + $this->assertEquals('url', $this->termsModel->getSearchUrl($dataObjectMock)); + } + + /** + * Terms data key provider + * + * @return array + */ + public function termKeysProvider(): array + { + return [ + [ + 'search', + true + ], + [ + '', + false + ] + ]; + } +} diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml index 9f421668bdc4f..47a0224a1c4db 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminUserLockWhenEditingUserTest.xml @@ -31,7 +31,7 @@ <actionGroup ref="AdminDeleteUserViaCurlActionGroup" stepKey="deleteUser"> <argument name="user" value="$$user$$" /> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminOpenUserEditPageActionGroup" stepKey="openEditUserPageFirstAttempt"> diff --git a/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminResetShippingOriginConfigurationActionGroup.xml b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminResetShippingOriginConfigurationActionGroup.xml new file mode 100644 index 0000000000000..0bc5153915cc5 --- /dev/null +++ b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminResetShippingOriginConfigurationActionGroup.xml @@ -0,0 +1,19 @@ +<?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="AdminResetShippingOriginConfigurationActionGroup"> + <annotations> + <description>Reset Shipping Origin configurations to default</description> + </annotations> + <createData entity="AdminResetShippingOrigin" stepKey="resetShippingOriginConfig"/> + <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddressConfigData.path}} ''" stepKey="setOriginStreetAddress"/> + <magentoCLI command="config:set {{AdminShippingSettingsOriginCityConfigData.path}} ''" stepKey="setOriginCity"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml new file mode 100644 index 0000000000000..ad92cade0b941 --- /dev/null +++ b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml @@ -0,0 +1,23 @@ +<?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="AdminSetShippingOriginConfigurationActionGroup"> + <annotations> + <description>Set Shipping Origin configurations</description> + </annotations> + <arguments> + <argument name="address" defaultValue="US_Address_California"/> + </arguments> + <magentoCLI command="config:set {{AdminShippingSettingsOriginCountryConfigData.path}} {{address.country_id}}" stepKey="setOriginCountry"/> + <magentoCLI command="config:set {{AdminShippingSettingsOriginCityConfigData.path}} {{address.city}}" stepKey="setOriginCity"/> + <magentoCLI command="config:set {{AdminShippingSettingsOriginZipCodeConfigData.path}} {{address.postcode}}" stepKey="setOriginZipCode"/> + <magentoCLI command="config:set {{AdminShippingSettingsOriginStreetAddressConfigData.path}} '{{address.street[0]}}'" stepKey="setOriginStreetAddress"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Shipping/Test/Mftf/Data/AdminShippingSettingsConfigData.xml b/app/code/Magento/Shipping/Test/Mftf/Data/AdminShippingSettingsConfigData.xml index 342472aab6f42..789be5aeb8784 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Data/AdminShippingSettingsConfigData.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Data/AdminShippingSettingsConfigData.xml @@ -33,4 +33,18 @@ <data key="hundred">100</data> <data key="default">0</data> </entity> + <entity name="AdminResetShippingOrigin" type="shipping_origin"> + <requiredEntity type="inheritCountryFlag">ShippingOriginCountryInheritValue</requiredEntity> + <requiredEntity type="inheritRegionFlag">ShippingOriginRegionInheritValue</requiredEntity> + <requiredEntity type="inheritPostcodeFlag">ShippingOriginPostcodeInheritValue</requiredEntity> + </entity> + <entity name="ShippingOriginCountryInheritValue" type="inheritCountryFlag"> + <data key="value">1</data> + </entity> + <entity name="ShippingOriginRegionInheritValue" type="inheritRegionFlag"> + <data key="value">1</data> + </entity> + <entity name="ShippingOriginPostcodeInheritValue" type="inheritPostcodeFlag"> + <data key="value">1</data> + </entity> </entities> diff --git a/app/code/Magento/Shipping/Test/Mftf/Metadata/shipping_origin-meta.xml b/app/code/Magento/Shipping/Test/Mftf/Metadata/shipping_origin-meta.xml new file mode 100644 index 0000000000000..e0f5e7afc4a9d --- /dev/null +++ b/app/code/Magento/Shipping/Test/Mftf/Metadata/shipping_origin-meta.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd"> + <operation name="ShippingOriginSetup" dataType="shipping_origin" type="create" auth="adminFormKey" url="/admin/system_config/save/section/shipping/" method="POST" successRegex="/messages-message-success/"> + <object key="groups" dataType="shipping_origin"> + <object key="origin" dataType="shipping_origin"> + <object key="fields" dataType="shipping_origin"> + <object key="country_id" dataType="shipping_origin"> + <object key="inherit" dataType="inheritCountryFlag"> + <field key="value">integer</field> + </object> + </object> + <object key="region_id" dataType="shipping_origin"> + <object key="inherit" dataType="inheritRegionFlag"> + <field key="value">integer</field> + </object> + </object> + <object key="postcode" dataType="shipping_origin"> + <object key="inherit" dataType="inheritPostcodeFlag"> + <field key="value">integer</field> + </object> + </object> + </object> + </object> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Shipping/Test/Mftf/Page/AdminShipmentNewPage.xml b/app/code/Magento/Shipping/Test/Mftf/Page/AdminShipmentNewPage.xml index 597abb5694e30..4ccda7ae7f2b1 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Page/AdminShipmentNewPage.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Page/AdminShipmentNewPage.xml @@ -8,7 +8,7 @@ <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminShipmentNewPage" url="order_shipment/new/order_id/" area="admin" module="Shipping"> + <page name="AdminShipmentNewPage" url="admin/order_shipment/new/order_id/" area="admin" module="Shipping"> <section name="AdminShipmentMainActionsSection"/> <section name="AdminShipmentOrderInformationSection"/> <section name="AdminShipmentAddressInformationSection"/> @@ -16,4 +16,4 @@ <section name="AdminShipmentItemsSection"/> <section name="AdminShipmentTotalSection"/> </page> -</pages> \ No newline at end of file +</pages> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckInputFieldsDisabledAfterAppConfigDumpTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckInputFieldsDisabledAfterAppConfigDumpTest.xml index 0b7ddd0cfa781..c3d9b243c27c7 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckInputFieldsDisabledAfterAppConfigDumpTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckInputFieldsDisabledAfterAppConfigDumpTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Assert configuration are disabled in Flat Rate section--> <comment userInput="Assert configuration are disabled in Flat Rate section" stepKey="commentSeeDisabledFlatRateConfigs"/> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckTheConfirmationPopupTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckTheConfirmationPopupTest.xml index 87058245c6014..bacfaf15f99d7 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckTheConfirmationPopupTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCheckTheConfirmationPopupTest.xml @@ -24,7 +24,7 @@ <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateOrderActionGroup" stepKey="goToCreateOrderPage"> <argument name="customer" value="$$createCustomer$$"/> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateOrderCustomStoreShippingMethodTableRatesTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateOrderCustomStoreShippingMethodTableRatesTest.xml index 7784fdd31e58e..5319992efa585 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateOrderCustomStoreShippingMethodTableRatesTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateOrderCustomStoreShippingMethodTableRatesTest.xml @@ -73,7 +73,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Assign product to custom website--> <amOnPage url="{{AdminProductEditPage.url($$createProduct.id$$)}}" stepKey="goToProductEditPage"/> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreatePartialShipmentEntityTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreatePartialShipmentEntityTest.xml index 0e4fd3ce9a86c..64d0932e9272d 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreatePartialShipmentEntityTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreatePartialShipmentEntityTest.xml @@ -35,7 +35,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShippingMethod"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- TEST BODY --> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateShipmentEntityTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateShipmentEntityTest.xml index f4087932a0710..0985aea2e502c 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateShipmentEntityTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminCreateShipmentEntityTest.xml @@ -35,7 +35,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShippingMethod"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- TEST BODY --> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminValidateShippingTrackingNumberTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminValidateShippingTrackingNumberTest.xml index ca4d731eb82b1..7df8f08e79530 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/AdminValidateShippingTrackingNumberTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminValidateShippingTrackingNumberTest.xml @@ -24,7 +24,7 @@ <after> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="CreateOrderActionGroup" stepKey="goToCreateOrderPage"> <argument name="customer" value="$$createCustomer$$"/> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/StorefrontDisplayTableRatesShippingMethodForAETest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/StorefrontDisplayTableRatesShippingMethodForAETest.xml index 81fe492ffc005..81c76ec916f7e 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/StorefrontDisplayTableRatesShippingMethodForAETest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/StorefrontDisplayTableRatesShippingMethodForAETest.xml @@ -39,7 +39,7 @@ <argument name="status" value="0"/> </actionGroup> <actionGroup ref="AdminSaveConfigActionGroup" stepKey="saveSystemConfig"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Admin Configuration: enable Table Rates and import CSV file with the rates--> <actionGroup ref="AdminOpenShippingMethodsConfigPageActionGroup" stepKey="openShippingMethodConfigPage"/> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/TableRatesShippingMethodForDifferentStatesTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/TableRatesShippingMethodForDifferentStatesTest.xml index 5721af7fdb71b..3a375be6533db 100644 --- a/app/code/Magento/Shipping/Test/Mftf/Test/TableRatesShippingMethodForDifferentStatesTest.xml +++ b/app/code/Magento/Shipping/Test/Mftf/Test/TableRatesShippingMethodForDifferentStatesTest.xml @@ -36,7 +36,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Stores > Configuration > Sales > Shipping Methods --> diff --git a/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml b/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml index b8fb91c4dcd99..e3275d4097c63 100644 --- a/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml +++ b/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml @@ -21,7 +21,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set fraud_protection/signifyd/active 0" stepKey="disableSignifyd"/> </after> diff --git a/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapCreateNewTest.xml b/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapCreateNewTest.xml index 57d8f8c75d23d..0ddc0640b56df 100644 --- a/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapCreateNewTest.xml +++ b/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapCreateNewTest.xml @@ -25,7 +25,7 @@ <argument name="filename" value="{{DefaultSiteMap.filename}}" /> </actionGroup> <actionGroup ref="AssertSiteMapDeleteSuccessActionGroup" stepKey="assertDeleteSuccessMessage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminMarketingSiteMapNavigateNewActionGroup" stepKey="navigateNewSiteMap"/> <actionGroup ref="AdminMarketingSiteMapFillFormActionGroup" stepKey="fillSiteMapForm"> diff --git a/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapNavigateMenuTest.xml b/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapNavigateMenuTest.xml index 54543fab8649d..608b284f247f3 100644 --- a/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapNavigateMenuTest.xml +++ b/app/code/Magento/Sitemap/Test/Mftf/Test/AdminMarketingSiteMapNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToMarketingSiteMapPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/Store/Controller/Store/Redirect.php b/app/code/Magento/Store/Controller/Store/Redirect.php index 51e6c2646e1ab..45924b5b0d28a 100644 --- a/app/code/Magento/Store/Controller/Store/Redirect.php +++ b/app/code/Magento/Store/Controller/Store/Redirect.php @@ -11,10 +11,15 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Session\Generic; +use Magento\Framework\Session\SidResolverInterface; use Magento\Store\Api\StoreRepositoryInterface; use Magento\Store\Api\StoreResolverInterface; use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Model\StoreResolver; use Magento\Store\Model\StoreSwitcher\HashGenerator; @@ -38,27 +43,35 @@ class Redirect extends Action implements HttpGetActionInterface, HttpPostActionI */ private $hashGenerator; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param Context $context * @param StoreRepositoryInterface $storeRepository * @param StoreResolverInterface $storeResolver - * @param \Magento\Framework\Session\Generic $session - * @param \Magento\Framework\Session\SidResolverInterface $sidResolver + * @param Generic $session + * @param SidResolverInterface $sidResolver * @param HashGenerator $hashGenerator + * @param StoreManagerInterface $storeManager * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( Context $context, StoreRepositoryInterface $storeRepository, StoreResolverInterface $storeResolver, - \Magento\Framework\Session\Generic $session, - \Magento\Framework\Session\SidResolverInterface $sidResolver, - HashGenerator $hashGenerator + Generic $session, + SidResolverInterface $sidResolver, + HashGenerator $hashGenerator, + StoreManagerInterface $storeManager = null ) { parent::__construct($context); $this->storeRepository = $storeRepository; $this->storeResolver = $storeResolver; $this->hashGenerator = $hashGenerator; + $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); } /** @@ -81,6 +94,9 @@ public function execute() try { /** @var Store $fromStore */ $fromStore = $this->storeRepository->get($fromStoreCode); + /** @var Store $targetStore */ + $targetStore = $this->storeRepository->get($targetStoreCode); + $this->storeManager->setCurrentStore($targetStore); } catch (NoSuchEntityException $e) { $error = __("Requested store is not found ({$fromStoreCode})"); } @@ -89,12 +105,11 @@ public function execute() $this->messageManager->addErrorMessage($error); $this->_redirect->redirect($this->_response, $currentStore->getBaseUrl()); } else { - $encodedUrl = $this->_request->getParam(\Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED); - + $encodedUrl = $this->_request->getParam(ActionInterface::PARAM_NAME_URL_ENCODED); $query = [ '___from_store' => $fromStore->getCode(), StoreResolverInterface::PARAM_NAME => $targetStoreCode, - \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => $encodedUrl, + ActionInterface::PARAM_NAME_URL_ENCODED => $encodedUrl, ]; $customerHash = $this->hashGenerator->generateHash($fromStore); @@ -104,6 +119,7 @@ public function execute() '_nosid' => true, '_query' => $query ]; + $this->_redirect->redirect($this->_response, 'stores/store/switch', $arguments); } diff --git a/app/code/Magento/Store/Model/Config/Processor/Fallback.php b/app/code/Magento/Store/Model/Config/Processor/Fallback.php index 91926cd23f9cf..57ac3459ccb48 100644 --- a/app/code/Magento/Store/Model/Config/Processor/Fallback.php +++ b/app/code/Magento/Store/Model/Config/Processor/Fallback.php @@ -172,7 +172,7 @@ private function getWebsiteConfig(array $websites, $id) foreach ((array)$this->websiteData as $website) { if ($website['website_id'] == $id) { $code = $website['code']; - return isset($websites[$code]) ? $websites[$code] : []; + return $websites[$code] ?? []; } } return []; diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml index 94e723c9afafb..d4b5bc9a9b50f 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusDisabledVerifyErrorSaveMessageTest.xml @@ -34,7 +34,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create store view selecting store created, choose disabled status and verify AssertStoreDisabledErrorSaveMessage--> @@ -44,4 +44,4 @@ <argument name="storeViewStatus" value="{{storeViewDataDisabled.is_active}}"/> </actionGroup> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml index 5d4ac8de74680..dc24a2f635b52 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyAbsenceOfDeleteButtonTest.xml @@ -29,7 +29,7 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteStore"> <argument name="storeGroupName" value="customStore.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index 2ba8c675b3b2a..188300acc7015 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateCustomStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -29,7 +29,7 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteStore"> <argument name="storeGroupName" value="customStore.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml index 6c60445107b28..faa9d38a2d6fe 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateNewLocalizedStoreViewStatusEnabledTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="storeViewGermany"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create new localized store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndDefaultCategoryTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndDefaultCategoryTest.xml index 4892556929f80..aaac3e5ea08b6 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndDefaultCategoryTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndDefaultCategoryTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store group with custom website and default category and verify AssertStoreGroupSuccessSaveMessage--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndRootCategoryTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndRootCategoryTest.xml index 27037f45f3835..8091f01e1f7ec 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndRootCategoryTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithCustomWebsiteAndRootCategoryTest.xml @@ -38,7 +38,7 @@ </actionGroup> <!--Delete root category--> <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store group with custom website and root category and verify AssertStoreGroupSuccessSaveMessage--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithDefaultWebsiteAndDefaultCategoryTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithDefaultWebsiteAndDefaultCategoryTest.xml index 0db65501b4112..a161abe767010 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithDefaultWebsiteAndDefaultCategoryTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreGroupWithDefaultWebsiteAndDefaultCategoryTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteStoreGroup"> <argument name="storeGroupName" value="SecondStoreGroupUnique.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store group with default website and default category and verify AssertStoreGroupSuccessSaveMessage--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml index 2d8fbc72263d4..0207faf692f14 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusDisabledVerifyBackendAndFrontendTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="storeViewDataDisabled"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml index 150e1082352cf..767b452544714 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewStatusEnabledVerifyBackendAndFrontendTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"> <argument name="customStore" value="storeViewData"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml index e20eb70ae6f45..4171aa6f08915 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateStoreViewTest.xml @@ -20,7 +20,7 @@ </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createStoreView" /> </before> @@ -29,7 +29,7 @@ <argument name="customStore" value="customStore"/> </actionGroup> <click selector="{{AdminStoresGridSection.resetButton}}" stepKey="resetSearchFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter grid and see created store view--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateWebsiteTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateWebsiteTest.xml index a8782acb1eb07..208ed316e2e51 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminCreateWebsiteTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminCreateWebsiteTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{customWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create website and AssertWebsiteSuccessSaveMessage--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteDefaultStoreViewTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteDefaultStoreViewTest.xml index 85fd8561f90b5..c010935233a5b 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteDefaultStoreViewTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteDefaultStoreViewTest.xml @@ -20,7 +20,7 @@ <actionGroup ref = "LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create custom store view--> <actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createNewStoreView"> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreGroupTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreGroupTest.xml index 185cf87531d9a..a3afddd794723 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreGroupTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreGroupTest.xml @@ -30,7 +30,7 @@ </before> <after> <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete custom store group and verify AssertStoreGroupSuccessDeleteAndBackupMessages--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreViewTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreViewTest.xml index df6fc391b2972..a197f88bafba2 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreViewTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminDeleteStoreViewTest.xml @@ -28,7 +28,7 @@ </before> <after> <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete custom store view and verify AssertStoreSuccessDeleteMessage And BackupMessage--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminMoveStoreToOtherGroupSameWebsiteTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminMoveStoreToOtherGroupSameWebsiteTest.xml index f1983dca53bf7..a94c1f8f66c7c 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminMoveStoreToOtherGroupSameWebsiteTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminMoveStoreToOtherGroupSameWebsiteTest.xml @@ -50,7 +50,7 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteSecondStore"> <argument name="storeGroupName" value="customStoreGroup.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Search created second store view in grid--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAcceptAlertAndVerifyStoreViewFormTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAcceptAlertAndVerifyStoreViewFormTest.xml index 16f830224f7f4..8d4e095d6ed87 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAcceptAlertAndVerifyStoreViewFormTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAcceptAlertAndVerifyStoreViewFormTest.xml @@ -44,7 +44,7 @@ </actionGroup> <!--Delete root category--> <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open created Store group in grid--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAndVerifyStoreViewFormTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAndVerifyStoreViewFormTest.xml index ab204560f11c6..f8df1059fb1ef 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAndVerifyStoreViewFormTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreGroupAndVerifyStoreViewFormTest.xml @@ -34,7 +34,7 @@ <actionGroup ref="DeleteCustomStoreActionGroup" stepKey="deleteUpdatedStoreGroup"> <argument name="storeGroupName" value="SecondStoreGroupUnique.name"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open created Store group in grid--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreViewTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreViewTest.xml index 26dee6c632928..3b16767e60d55 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreViewTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateStoreViewTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteUpdatedStoreView"> <argument name="customStore" value="SecondStoreUnique"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Search created store view in grid--> diff --git a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateWebsiteTest.xml b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateWebsiteTest.xml index 5c4ecb87dda53..e9f72e46e3973 100644 --- a/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateWebsiteTest.xml +++ b/app/code/Magento/Store/Test/Mftf/Test/AdminUpdateWebsiteTest.xml @@ -30,7 +30,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> <argument name="websiteName" value="{{updateCustomWebsite.name}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Search created custom website in grid--> diff --git a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php index 4408c45d6a640..cb92f14e6227c 100755 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -20,6 +20,7 @@ use Magento\Store\Api\StoreResolverInterface; use Magento\Store\Controller\Store\Redirect; use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Model\StoreResolver; use Magento\Store\Model\StoreSwitcher\HashGenerator; use PHPUnit\Framework\MockObject\MockObject; @@ -31,8 +32,20 @@ */ class RedirectTest extends TestCase { - private const DEFAULT_STORE_VIEW_CODE = 'default'; - private const STORE_CODE = 'sv1'; + /** + * Stub for default store view code + */ + private const STUB_DEFAULT_STORE_VIEW_CODE = 'default'; + + /** + * Stub for default store code + */ + private const STUB_STORE_CODE = 'sv1'; + + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManagerMock; /** * @var StoreRepositoryInterface|MockObject @@ -67,7 +80,12 @@ class RedirectTest extends TestCase /** * @var Store|MockObject */ - private $formStoreMock; + private $fromStoreMock; + + /** + * @var Store|MockObject + */ + private $targetStoreMock; /** * @var Store|MockObject @@ -87,13 +105,14 @@ class RedirectTest extends TestCase /** * @var Redirect */ - private $redirectController; + private $model; /** * @inheritDoc */ protected function setUp() { + $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); $this->requestMock = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->setMethods(['getParam']) @@ -117,7 +136,11 @@ protected function setUp() $this->responseMock = $this->getMockBuilder(ResponseInterface::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->formStoreMock = $this->getMockBuilder(Store::class) + $this->fromStoreMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + $this->targetStoreMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() ->setMethods(['getCode']) ->getMockForAbstractClass(); @@ -150,9 +173,10 @@ protected function setUp() 'messageManager' => $this->messageManagerMock, ] ); - $this->redirectController = $objectManager->getObject( + $this->model = $objectManager->getObject( Redirect::class, [ + 'storeManager' => $this->storeManagerMock, 'storeRepository' => $this->storeRepositoryMock, 'storeResolver' => $this->storeResolverMock, 'sidResolver' => $this->sidResolverMock, @@ -186,19 +210,25 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v $defaultStoreViewCode ); $this->storeRepositoryMock - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('get') - ->with($defaultStoreViewCode) - ->willReturn($this->formStoreMock); - $this->formStoreMock + ->willReturnMap([ + [$defaultStoreViewCode, $this->fromStoreMock], + [$storeCode, $this->targetStoreMock], + ]); + $this->fromStoreMock ->expects($this->once()) ->method('getCode') ->willReturn($defaultStoreViewCode); $this->hashGeneratorMock ->expects($this->once()) ->method('generateHash') - ->with($this->formStoreMock) + ->with($this->fromStoreMock) ->willReturn([]); + $this->storeManagerMock + ->expects($this->once()) + ->method('setCurrentStore') + ->with($this->targetStoreMock); $this->redirectMock ->expects($this->once()) ->method('redirect') @@ -214,7 +244,7 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v ] ); - $this->assertEquals(null, $this->redirectController->execute()); + $this->assertEquals(null, $this->model->execute()); } /** @@ -257,7 +287,7 @@ public function testRedirectWithThrowsException(string $defaultStoreViewCode, st ->with($this->responseMock, $this->currentStoreMock) ->willReturnSelf(); - $this->assertEquals(null, $this->redirectController->execute()); + $this->assertEquals(null, $this->model->execute()); } /** @@ -281,7 +311,7 @@ public function testRedirectTargetIsNull(): void ->expects($this->never()) ->method('get'); - $this->assertEquals($this->responseMock, $this->redirectController->execute()); + $this->assertEquals($this->responseMock, $this->model->execute()); } /** @@ -292,7 +322,7 @@ public function testRedirectTargetIsNull(): void public function getConfigDataProvider(): array { return [ - [self::DEFAULT_STORE_VIEW_CODE, self::STORE_CODE] + [self::STUB_DEFAULT_STORE_VIEW_CODE, self::STUB_STORE_CODE] ]; } } diff --git a/app/code/Magento/Store/Test/Unit/Model/InformationTest.php b/app/code/Magento/Store/Test/Unit/Model/InformationTest.php index 0fc2f635f069d..a30446165bb29 100644 --- a/app/code/Magento/Store/Test/Unit/Model/InformationTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/InformationTest.php @@ -63,7 +63,7 @@ protected function setUp() $this->store->expects($this->any()) ->method('getConfig') ->willReturnCallback(function ($path) use ($mockData) { - return isset($mockData[$path]) ? $mockData[$path] : null; + return $mockData[$path] ?? null; }); $this->renderer = $this->getMockBuilder(\Magento\Store\Model\Address\Renderer::class) diff --git a/app/code/Magento/Store/etc/frontend/sections.xml b/app/code/Magento/Store/etc/frontend/sections.xml index b7dbfe405263b..85f3627e05c95 100644 --- a/app/code/Magento/Store/etc/frontend/sections.xml +++ b/app/code/Magento/Store/etc/frontend/sections.xml @@ -7,6 +7,10 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"> - <action name="stores/store/switch"/> - <action name="stores/store/switchrequest"/> + <action name="stores/store/switch"> + <section name="*"/> + </action> + <action name="stores/store/switchrequest"> + <section name="*"/> + </action> </config> diff --git a/app/code/Magento/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index f9a600925b2a9..d2cd1baca894b 100644 --- a/app/code/Magento/Swatches/Helper/Data.php +++ b/app/code/Magento/Swatches/Helper/Data.php @@ -35,7 +35,7 @@ class Data const EMPTY_IMAGE_VALUE = 'no_selection'; /** - * Default store ID + * The int value of the Default store ID */ const DEFAULT_STORE_ID = 0; @@ -471,13 +471,13 @@ public function getSwatchesByOptionsId(array $optionIds) $swatches = []; $fallbackValues = []; $currentStoreId = $this->storeManager->getStore()->getId(); - foreach ($swatchCollection as $item) { + foreach ($swatchCollection->getData() as $item) { if ($item['type'] != Swatch::SWATCH_TYPE_TEXTUAL) { - $swatches[$item['option_id']] = $item->getData(); + $swatches[$item['option_id']] = $item; } elseif ($item['store_id'] == $currentStoreId && $item['value'] != '') { - $fallbackValues[$item['option_id']][$currentStoreId] = $item->getData(); + $fallbackValues[$item['option_id']][$currentStoreId] = $item; } elseif ($item['store_id'] == self::DEFAULT_STORE_ID) { - $fallbackValues[$item['option_id']][self::DEFAULT_STORE_ID] = $item->getData(); + $fallbackValues[$item['option_id']][self::DEFAULT_STORE_ID] = $item; } } diff --git a/app/code/Magento/Swatches/Test/Mftf/Section/AdminManageSwatchSection.xml b/app/code/Magento/Swatches/Test/Mftf/Section/AdminManageSwatchSection.xml index c3ef0a7324bfd..629599eba84fe 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Section/AdminManageSwatchSection.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Section/AdminManageSwatchSection.xml @@ -17,6 +17,8 @@ <element name="nthSwatchText" type="input" selector="#swatch-text-options-panel table tbody tr:nth-of-type({{var}}) td:nth-of-type(3) input" parameterized="true"/> <element name="nthIsDefault" type="input" selector="(//input[@name='defaultvisual[]'])[{{var}}]" parameterized="true"/> <element name="nthSwatchAdminDescription" type="input" selector="#swatch-text-options-panel table tbody tr:nth-of-type({{var}}) td:nth-of-type(4) input" parameterized="true"/> + <element name="nthVisualSwatch" type="button" selector="#swatch-visual-options-panel table tbody tr:nth-of-type({{var}}) .swatches-visual-col" parameterized="true"/> + <element name="chooserBlock" type="block" selector="#swatch-visual-options-panel table tbody tr:nth-of-type({{var}}) .swatches-visual-col .swatch_sub-menu_container" parameterized="true"/> <!-- Selector for Admin Description input where the index is zero-based --> <element name="swatchAdminDescriptionByIndex" type="input" selector="input[name='optiontext[value][option_{{index}}][0]']" parameterized="true"/> <element name="nthChooseColor" type="button" selector="#swatch-visual-options-panel table tbody tr:nth-of-type({{var}}) .swatch_row_name.colorpicker_handler" parameterized="true"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCheckColorUploadChooserVisualSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCheckColorUploadChooserVisualSwatchTest.xml new file mode 100644 index 0000000000000..65ac017072917 --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCheckColorUploadChooserVisualSwatchTest.xml @@ -0,0 +1,39 @@ +<?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="AdminCheckColorUploadChooserVisualSwatchTest"> + <annotations> + <features value="Swatches"/> + <stories value="Check correct view of visual swatches"/> + <title value="Correct view of Swatches while choosing color or upload image"/> + <description value="Correct view of Swatches while choosing color or upload image"/> + <severity value="AVERAGE"/> + <group value="Swatches"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <amOnPage url="{{ProductAttributePage.url}}" stepKey="addNewProductAttribute"/> + <selectOption selector="{{AttributePropertiesSection.InputType}}" + userInput="{{visualSwatchAttribute.input_type}}" stepKey="fillInputType"/> + + <click selector="{{AdminManageSwatchSection.addSwatch}}" stepKey="clickAddSwatch1"/> + <click selector="{{AdminManageSwatchSection.addSwatch}}" stepKey="clickAddSwatch2"/> + <click selector="{{AdminManageSwatchSection.addSwatch}}" stepKey="clickAddSwatch3"/> + <click selector="{{AdminManageSwatchSection.nthVisualSwatch('3')}}" stepKey="clickSwatch3"/> + + <click selector="{{AdminManageSwatchSection.nthVisualSwatch('2')}}" stepKey="clickSwatch2"/> + <seeElement selector="{{AdminManageSwatchSection.chooserBlock('2')}}" stepKey="seeSwatch2"/> + <dontSeeElement selector="{{AdminManageSwatchSection.chooserBlock('3')}}" stepKey="dontSeeSwatch3"/> + + <click selector="{{AdminManageSwatchSection.nthVisualSwatch('1')}}" stepKey="clickSwatch1"/> + <seeElement selector="{{AdminManageSwatchSection.chooserBlock('1')}}" stepKey="seeSwatch1"/> + <dontSeeElement selector="{{AdminManageSwatchSection.chooserBlock('2')}}" stepKey="dontSeeSwatch2"/> + </test> +</tests> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 8a2683af83dc1..0e24d63728d9d 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -24,7 +24,14 @@ </before> <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> + <argument name="sku" value="{{BaseConfigurableProduct.sku}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"/> + <actionGroup ref="NavigateToAndResetProductAttributeGridToDefaultViewActionGroup" stepKey="resetProductAttributeFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- Begin creating a new product attribute of type "Image Swatch" --> @@ -96,15 +103,11 @@ </assertContains> <!-- Create a configurable product to verify the storefront with --> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="amOnProductGridPage"/> - <waitForPageLoad time="30" stepKey="waitForProductGrid"/> - <actionGroup ref="GoToCreateProductPageActionGroup" stepKey="goToCreateConfigurableProduct"> - <argument name="product" value="BaseConfigurableProduct"/> - </actionGroup> + <amOnPage url="{{AdminProductCreatePage.url(BaseConfigurableProduct.attribute_set_id, BaseConfigurableProduct.type_id)}}" stepKey="goToCreateConfigurableProduct"/> <actionGroup ref="FillMainProductFormActionGroup" stepKey="fillProductForm"> <argument name="product" value="BaseConfigurableProduct"/> </actionGroup> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$createCategory.name$$]" stepKey="fillCategory"/> + <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$createCategory.name$]" stepKey="fillCategory"/> <!-- Create configurations based off the Image Swatch we created earlier --> <click selector="{{AdminProductFormConfigurationsSection.createConfigurations}}" stepKey="clickCreateConfigurations"/> @@ -144,7 +147,7 @@ </assertContains> <!-- Go to the product listing page and see text swatch options --> - <amOnPage url="$$createCategory.name$$.html" stepKey="goToCategoryPageStorefront"/> + <amOnPage url="$createCategory.custom_attributes[url_key]$.html" stepKey="goToCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForProductListingPage"/> <!-- Verify the storefront --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateTextSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateTextSwatchTest.xml index 4685670fbfdd2..b01dff6a8ca06 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateTextSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateTextSwatchTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Create a new product attribute of type "Text Swatch" --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchTest.xml index 1c8e86b3765d4..7599111260980 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchTest.xml @@ -35,7 +35,7 @@ <waitForPageLoad stepKey="waitToClickSave"/> <click selector="{{AttributePropertiesSection.SaveAndEdit}}" stepKey="clickSaveAndEdit"/> <!-- Logout --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Go to the edit page for the "color" attribute --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml index 8e63a14413f2f..5660922962b47 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml @@ -24,7 +24,7 @@ <actionGroup ref="DeleteProductAttributeActionGroup" stepKey="deleteAttribute"> <argument name="ProductAttribute" value="visualSwatchAttribute"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{ProductAttributePage.url}}" stepKey="navigateToNewProductAttributePage"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminDisablingSwatchTooltipsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminDisablingSwatchTooltipsTest.xml index b44c04d2c1b46..7d3d1aafd8d6d 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminDisablingSwatchTooltipsTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminDisablingSwatchTooltipsTest.xml @@ -37,7 +37,7 @@ <click selector="{{AttributePropertiesSection.SaveAndEdit}}" stepKey="clickSaveAndEdit"/> <!-- Log out --> - <actionGroup ref="logout" stepKey="logOut"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logOut"/> <!-- Delete category --> <deleteData stepKey="deleteCategory" createDataKey="createCategory"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSaveConfigurableProductWithAttributesImagesAndSwatchesTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSaveConfigurableProductWithAttributesImagesAndSwatchesTest.xml index d034faeefbdc0..0ca0561be0a0d 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSaveConfigurableProductWithAttributesImagesAndSwatchesTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSaveConfigurableProductWithAttributesImagesAndSwatchesTest.xml @@ -71,7 +71,7 @@ <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPage"/> <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearProductsGridFilter"/> <!-- Admin logout --> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Add created product attribute to the Default set --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml index b24420061db65..d5bc8dbadfb56 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml @@ -27,7 +27,7 @@ <after> <!-- Log out --> <comment userInput="Log out" stepKey="commentLogOut"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to Admin > Content > Configuration page --> <comment userInput="Go to Configuration Page" stepKey="commentOpenConfigurationPage"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableProductSwatchMinimumPriceTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableProductSwatchMinimumPriceTest.xml index 1cfa7da6f3410..6651692bcada4 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableProductSwatchMinimumPriceTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableProductSwatchMinimumPriceTest.xml @@ -40,7 +40,7 @@ <argument name="ProductAttribute" value="ProductSizeAttribute"/> </actionGroup> <!-- Logout --> - <actionGroup ref="logout" stepKey="amOnLogoutPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> </after> <!--Create text swatch attribute with 3 options: Black, White and Blue--> <actionGroup ref="AddTextSwatchToProductActionGroup" stepKey="addColorAttribute"> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml index 0c179e92adc8d..427797bdb09e2 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByImageSwatchTest.xml @@ -30,7 +30,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Begin creating a new product attribute --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByTextSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByTextSwatchTest.xml index 0024a95360ef2..1d1c5c9c4e683 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByTextSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByTextSwatchTest.xml @@ -28,7 +28,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Begin creating a new product attribute --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByVisualSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByVisualSwatchTest.xml index 3cd2e13c9d75d..0b6238d7d46be 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByVisualSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontFilterByVisualSwatchTest.xml @@ -30,7 +30,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <!-- Begin creating a new product attribute --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontImageColorWhenFilterByColorFilterTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontImageColorWhenFilterByColorFilterTest.xml index 208f5cecc6fa9..18e9f82e74121 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontImageColorWhenFilterByColorFilterTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontImageColorWhenFilterByColorFilterTest.xml @@ -39,7 +39,7 @@ <argument name="perPage" value="100"/> </actionGroup> <actionGroup ref="DeleteProductsIfTheyExistActionGroup" stepKey="deleteAllProducts"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <amOnPage url="{{AdminProductEditPage.url($$createConfigProduct.id$$)}}" stepKey="navigateToConfigProductPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSeeProductImagesMatchingProductSwatchesTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSeeProductImagesMatchingProductSwatchesTest.xml index d3f6a2e6ccff7..8bfdb77cbe177 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSeeProductImagesMatchingProductSwatchesTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSeeProductImagesMatchingProductSwatchesTest.xml @@ -34,7 +34,7 @@ <argument name="product" value="$$createSimpleProduct$$"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductGridFilter"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Begin creating a new product attribute --> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml index 119a645252685..9acfdf394be4b 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchAttributesDisplayInWidgetCMSTest.xml @@ -51,7 +51,7 @@ <waitForElementVisible selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="waitForPageReloadAfterDeleteDefaultCategory"/> <magentoCLI command="config:set cms/wysiwyg/enabled enabled" stepKey="enableWYSIWYG"/> <!--logout--> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Login--> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdmin"/> @@ -77,7 +77,7 @@ <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickToExpandSEOSection"/> <scrollTo selector="{{CmsNewPagePageSeoSection.urlKey}}" stepKey="scrollToUrlKey"/> <grabValueFrom selector="{{CmsNewPagePageSeoSection.urlKey}}" stepKey="grabTextFromUrlKey"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!--Open Storefront page for the new created page--> <amOnPage url="{{StorefrontHomePage.url}}$grabTextFromUrlKey" stepKey="gotToCreatedCmsPage"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchProductWithFileCustomOptionTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchProductWithFileCustomOptionTest.xml index 99b38bd3b34d6..5c0ad3bc4ea77 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchProductWithFileCustomOptionTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontSwatchProductWithFileCustomOptionTest.xml @@ -26,7 +26,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php index aa44f1f114037..1b4ab2f4c203b 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php @@ -669,7 +669,8 @@ public function dataForGettingSwatchAsArray() public function testGetSwatchesByOptionsIdIf1() { - $swatchMock = $this->createMock(\Magento\Swatches\Model\Swatch::class); + //Simulate behaviour of \Magento\Swatches\Model\Swatch as array item + $swatchMock = $this->createMock(\ArrayAccess::class); $optionsData = [ [ @@ -692,22 +693,18 @@ public function testGetSwatchesByOptionsIdIf1() ->willReturn($optionsData[0]['type']); $swatchMock->expects($this->at(1))->method('offsetGet')->with('option_id') ->willReturn($optionsData[0]['option_id']); - $swatchMock->expects($this->at(2))->method('getData')->with('') - ->willReturn($optionsData[0]); - $swatchMock->expects($this->at(3))->method('offsetGet')->with('type') + $swatchMock->expects($this->at(2))->method('offsetGet')->with('type') ->willReturn($optionsData[1]['type']); - $swatchMock->expects($this->at(4))->method('offsetGet')->with('store_id') + $swatchMock->expects($this->at(3))->method('offsetGet')->with('store_id') ->willReturn($optionsData[1]['store_id']); - $swatchMock->expects($this->at(5))->method('offsetGet')->with('store_id') + $swatchMock->expects($this->at(4))->method('offsetGet')->with('store_id') ->willReturn($optionsData[1]['store_id']); - $swatchMock->expects($this->at(6))->method('offsetGet')->with('option_id') + $swatchMock->expects($this->at(5))->method('offsetGet')->with('option_id') ->willReturn($optionsData[1]['option_id']); - $swatchMock->expects($this->at(7))->method('getData')->with('') - ->willReturn($optionsData[1]); - $swatchCollectionMock = $this->objectManager - ->getCollectionMock(Collection::class, [$swatchMock, $swatchMock]); + $swatchCollectionMock = $this->createMock(Collection::class); $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); + $swatchCollectionMock->expects($this->once())->method('getData')->willReturn([$swatchMock, $swatchMock]); $this->swatchCollectionFactoryMock->method('create')->willReturn($swatchCollectionMock); $storeMock = $this->createMock(\Magento\Store\Model\Store::class); @@ -719,7 +716,8 @@ public function testGetSwatchesByOptionsIdIf1() public function testGetSwatchesByOptionsIdIf2() { - $swatchMock = $this->createMock(\Magento\Swatches\Model\Swatch::class); + //Simulate behaviour of \Magento\Swatches\Model\Swatch as array item + $swatchMock = $this->createMock(\ArrayAccess::class); $optionsData = [ [ @@ -737,28 +735,21 @@ public function testGetSwatchesByOptionsIdIf2() 'id' => 488, ] ]; - - $swatchMock->expects($this->at(0))->method('offsetGet')->with('type')->willReturn(0); - $swatchMock->expects($this->at(1))->method('offsetGet')->with('store_id')->willReturn(1); - $swatchMock->expects($this->at(2))->method('offsetGet')->with('value')->willReturn('test'); - $swatchMock->expects($this->at(3))->method('offsetGet')->with('option_id')->willReturn(35); - $swatchMock->expects($this->at(4))->method('getData')->with('')->willReturn($optionsData[0]); - $swatchMock->expects($this->at(5))->method('offsetGet')->with('type')->willReturn(0); - $swatchMock->expects($this->at(6))->method('offsetGet')->with('store_id')->willReturn(1); - $swatchMock->expects($this->at(7))->method('offsetGet')->with('value')->willReturn('test2'); - $swatchMock->expects($this->at(8))->method('offsetGet')->with('option_id')->willReturn(36); - $swatchMock->expects($this->at(9))->method('getData')->with('')->willReturn($optionsData[1]); - - $swatchCollectionMock = $this->objectManager->getCollectionMock( - Collection::class, - [ - $swatchMock, - $swatchMock, - ] - ); + // @codingStandardsIgnoreStart + $swatchMock->expects($this->at(0))->method('offsetGet')->with('type')->willReturn($optionsData[0]['type']); + $swatchMock->expects($this->at(1))->method('offsetGet')->with('store_id')->willReturn($optionsData[0]['store_id']); + $swatchMock->expects($this->at(2))->method('offsetGet')->with('value')->willReturn($optionsData[0]['value']); + $swatchMock->expects($this->at(3))->method('offsetGet')->with('option_id')->willReturn($optionsData[0]['option_id']); + $swatchMock->expects($this->at(4))->method('offsetGet')->with('type')->willReturn($optionsData[1]['type']); + $swatchMock->expects($this->at(5))->method('offsetGet')->with('store_id')->willReturn($optionsData[1]['store_id']); + $swatchMock->expects($this->at(6))->method('offsetGet')->with('value')->willReturn($optionsData[1]['value']); + $swatchMock->expects($this->at(7))->method('offsetGet')->with('option_id')->willReturn($optionsData[1]['option_id']); + // @codingStandardsIgnoreEnd + $swatchCollectionMock = $this->createMock(Collection::class); $this->swatchCollectionFactoryMock->method('create')->willReturn($swatchCollectionMock); $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); + $swatchCollectionMock->expects($this->once())->method('getData')->willReturn([$swatchMock, $swatchMock]); $storeMock = $this->createMock(\Magento\Store\Model\Store::class); $this->storeManagerMock->method('getStore')->willReturn($storeMock); @@ -769,7 +760,8 @@ public function testGetSwatchesByOptionsIdIf2() public function testGetSwatchesByOptionsIdIf3() { - $swatchMock = $this->createMock(\Magento\Swatches\Model\Swatch::class); + //Simulate behaviour of \Magento\Swatches\Model\Swatch as array item + $swatchMock = $this->createMock(\ArrayAccess::class); $optionsData = [ 'type' => 0, @@ -778,22 +770,17 @@ public function testGetSwatchesByOptionsIdIf3() 'option_id' => 35, 'id' => 423, ]; - - $swatchMock->expects($this->at(0))->method('offsetGet')->with('type')->willReturn(0); - $swatchMock->expects($this->at(1))->method('offsetGet')->with('store_id')->willReturn(0); - $swatchMock->expects($this->at(2))->method('offsetGet')->with('store_id')->willReturn(0); - $swatchMock->expects($this->at(3))->method('offsetGet')->with('option_id')->willReturn(35); - $swatchMock->expects($this->at(4))->method('getData')->with('')->willReturn($optionsData); - - $swatchCollectionMock = $this->objectManager->getCollectionMock( - Collection::class, - [ - $swatchMock, - ] - ); + // @codingStandardsIgnoreStart + $swatchMock->expects($this->at(0))->method('offsetGet')->with('type')->willReturn($optionsData['type']); + $swatchMock->expects($this->at(1))->method('offsetGet')->with('store_id')->willReturn($optionsData['store_id']); + $swatchMock->expects($this->at(2))->method('offsetGet')->with('store_id')->willReturn($optionsData['store_id']); + $swatchMock->expects($this->at(3))->method('offsetGet')->with('option_id')->willReturn($optionsData['option_id']); + // @codingStandardsIgnoreEnd + $swatchCollectionMock = $this->createMock(Collection::class); $this->swatchCollectionFactoryMock->method('create')->willReturn($swatchCollectionMock); $swatchCollectionMock->method('addFilterByOptionsIds')->with([35])->will($this->returnSelf()); + $swatchCollectionMock->expects($this->once())->method('getData')->willReturn([$swatchMock]); $storeMock = $this->createMock(\Magento\Store\Model\Store::class); $this->storeManagerMock->method('getStore')->willReturn($storeMock); diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js b/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js index 19307432c4122..c27d2e60b2899 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/visual.js @@ -404,8 +404,11 @@ define([ /** * Toggle color upload chooser */ - $(document).on('click', '.swatch_window', function () { - $(this).next('div').toggle(); + $(document).on('click', '.swatches-visual-col', function () { + var currentElement = $(this).find('.swatch_sub-menu_container'); + + jQuery('.swatch_sub-menu_container').not(currentElement).hide(); + currentElement.toggle(); }); }); }; diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index aa7b6c7a076ea..8b5dfcd80deb4 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -723,7 +723,9 @@ define([ $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass), attributeId = $parent.attr('attribute-id'), $input = $parent.find('.' + $widget.options.classes.attributeInput), - checkAdditionalData = JSON.parse(this.options.jsonSwatchConfig[attributeId]['additional_data']); + checkAdditionalData = JSON.parse(this.options.jsonSwatchConfig[attributeId]['additional_data']), + $priceBox = $widget.element.parents($widget.options.selectorProduct) + .find(this.options.selectorProductPrice); if ($widget.inProductList) { $input = $widget.productForm.find( @@ -751,16 +753,15 @@ define([ $widget._Rebuild(); - if ($widget.element.parents($widget.options.selectorProduct) - .find(this.options.selectorProductPrice).is(':data(mage-priceBox)') - ) { + if ($priceBox.is(':data(mage-priceBox)')) { $widget._UpdatePrice(); } $(document).trigger('updateMsrpPriceBlock', [ this._getSelectedOptionPriceIndex(), - $widget.options.jsonConfig.optionPrices + $widget.options.jsonConfig.optionPrices, + $priceBox ]); if (parseInt(checkAdditionalData['update_product_preview_image'], 10) === 1) { diff --git a/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php b/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php index 29ce7e6d4b0aa..1884b247e530a 100644 --- a/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php +++ b/app/code/Magento/Tax/Block/Adminhtml/Rate/Form.php @@ -211,7 +211,12 @@ protected function _prepareForm() $fieldset->addField( 'zip_is_range', 'checkbox', - ['name' => 'zip_is_range', 'label' => __('Zip/Post is Range'), 'value' => '1'] + [ + 'name' => 'zip_is_range', + 'label' => __('Zip/Post is Range'), + 'value' => '1', + 'class' => 'zip-is-range-checkbox' + ] ); if (!isset($formData['tax_postcode'])) { diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxActionGroup.xml new file mode 100644 index 0000000000000..cb8e40c3b962c --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxActionGroup.xml @@ -0,0 +1,24 @@ +<?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="AssertStorefrontCartItemExcludingTaxActionGroup"> + <annotations> + <description>Validates that the provided product price and subtotal excluding tax are present and correct in the Shopping Cart.</description> + </annotations> + <arguments> + <argument name="productName" defaultValue="{{_defaultProduct.name}}" type="string"/> + <argument name="productPriceExcludingTax" defaultValue="150" type="string"/> + <argument name="productSubtotalExcludingTax" defaultValue="150" type="string"/> + </arguments> + + <see userInput="{{productPriceExcludingTax}}" selector="{{StorefrontCheckoutCartItemTaxSection.productPriceExcludingTaxByName(productName)}}" stepKey="assertProductPriceExcludingTax"/> + <see userInput="{{productSubtotalExcludingTax}}" selector="{{StorefrontCheckoutCartItemTaxSection.productSubtotalExcludingTaxByName(productName)}}" stepKey="assertProductSubtotalExcludingTax"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountActionGroup.xml new file mode 100644 index 0000000000000..9a1f60e7433d9 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountActionGroup.xml @@ -0,0 +1,25 @@ +<?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="AssertStorefrontCheckoutCartTaxAmountActionGroup"> + <annotations> + <description>Check tax summary data in Summary section of shopping cart on storefront</description> + </annotations> + <arguments> + <argument name="taxAmount" type="string" defaultValue="$0.83"/> + <argument name="rate" type="string" defaultValue="US-CA-*-Rate 1 (8.25%)"/> + </arguments> + + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="{{taxAmount}}" stepKey="checkTaxAmount" /> + <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary" /> + <conditionalClick selector="{{CheckoutCartSummarySection.taxSummary}}" dependentSelector="{{CheckoutCartSummarySection.rate}}" visible="false" stepKey="expandTaxSummary"/> + <see selector="{{CheckoutCartSummarySection.rate}}" userInput="{{rate}}" stepKey="checkRate" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxActionGroup.xml new file mode 100644 index 0000000000000..9497f41ec0d57 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxActionGroup.xml @@ -0,0 +1,32 @@ +<?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="AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxActionGroup"> + <annotations> + <description>Validates that the provided Subtotal/Total excluding and including tax are present and correct on shopping cart page.</description> + </annotations> + <arguments> + <argument name="subtotalExcludingTax" defaultValue="100" type="string"/> + <argument name="subtotalIncludingTax" defaultValue="108.25" type="string"/> + <argument name="tax" defaultValue="8.25" type="string"/> + <argument name="total" defaultValue="113.25" type="string"/> + </arguments> + + <seeInCurrentUrl url="{{CheckoutCartPage.url}}" stepKey="assertUrl"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotalExcludingTax}}" stepKey="waitForSubtotalVisible"/> + <see selector="{{CheckoutCartSummarySection.subtotalExcludingTax}}" userInput="{{subtotalExcludingTax}}" stepKey="assertSubtotalExcludingTax"/> + <see selector="{{CheckoutCartSummarySection.subtotalIncludingTax}}" userInput="{{subtotalIncludingTax}}" stepKey="assertSubtotalIncludingTax"/> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="{{tax}}" stepKey="assertTaxAmount"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.total}}" stepKey="waitForTotalVisible"/> + <waitForElementVisible selector="{{CheckoutCartSummarySection.totalAmount(total)}}" stepKey="waitForTotalAmountVisible"/> + <see selector="{{CheckoutCartSummarySection.total}}" userInput="{{total}}" stepKey="assertTotal"/> + <seeElement selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="seeProceedToCheckoutButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml b/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml index ad92bae51d429..d1f77a69f69f4 100644 --- a/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml +++ b/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml @@ -16,6 +16,12 @@ <data key="value">*</data> </entity> <!-- Shopping Cart Display Settings --> + <entity name="IncludeAndExcludeTaxInCartPrice" type="priceCart"> + <data key="value">3</data> + </entity> + <entity name="IncludeAndExcludeTaxInCartSubtotal" type="subtotalCart"> + <data key="value">3</data> + </entity> <entity name="IncludeTaxInOrderTotalCart" type="grandtotalCart"> <data key="value">1</data> </entity> @@ -57,6 +63,22 @@ <entity name="EmptyField" type="taxPostCodeEmpty"> <data key="value"/> </entity> + <entity name="TaxConfigExcludeAndIncludeTaxInCart" type="tax_config_state"> + <!-- Shopping Cart Display Settings --> + <requiredEntity type="priceCart">IncludeAndExcludeTaxInCartPrice</requiredEntity> + <requiredEntity type="subtotalCart">IncludeAndExcludeTaxInCartSubtotal</requiredEntity> + </entity> + <!-- Orders, Invoices, Credit Memos Display Settings--> + <entity name="IncludeAndExcludeTaxInSalesPrice" type="priceSales"> + <data key="value">3</data> + </entity> + <entity name="IncludeAndExcludeTaxInSalesSubtotal" type="subtotalSales"> + <data key="value">3</data> + </entity> + <entity name="TaxConfigExcludeAndIncludeTaxInSales" type="tax_config_state"> + <requiredEntity type="priceSales">IncludeAndExcludeTaxInSalesPrice</requiredEntity> + <requiredEntity type="subtotalSales">IncludeAndExcludeTaxInSalesSubtotal</requiredEntity> + </entity> <entity name="DefaultProductTaxClass"> <!-- Default value --> <data key="path">tax/classes/default_product_tax_class</data> diff --git a/app/code/Magento/Tax/Test/Mftf/Metadata/tax_config-meta.xml b/app/code/Magento/Tax/Test/Mftf/Metadata/tax_config-meta.xml index 7383e9c580283..848c5de375275 100644 --- a/app/code/Magento/Tax/Test/Mftf/Metadata/tax_config-meta.xml +++ b/app/code/Magento/Tax/Test/Mftf/Metadata/tax_config-meta.xml @@ -24,9 +24,15 @@ </object> <object key="cart_display" dataType="tax_config_state"> <object key="fields" dataType="tax_config_state"> - <object key="grandtotal" dataType="grandtotalCart"> - <field key="value">string</field> - </object> + <object key="price" dataType="priceCart"> + <field key="value">string</field> + </object> + <object key="subtotal" dataType="subtotalCart"> + <field key="value">string</field> + </object> + <object key="grandtotal" dataType="grandtotalCart"> + <field key="value">string</field> + </object> <object key="full_summary" dataType="full_summaryCart"> <field key="value">string</field> </object> @@ -35,6 +41,16 @@ </object> </object> </object> + <object key="sales_display" dataType="tax_config_state"> + <object key="fields" dataType="tax_config_state"> + <object key="price" dataType="priceSales"> + <field key="value">string</field> + </object> + <object key="subtotal" dataType="subtotalSales"> + <field key="value">string</field> + </object> + </object> + </object> </object> </operation> <operation name="TaxConfigDefaultsTaxDestination" dataType="tax_config_default" type="create" auth="adminFormKey" url="/admin/system_config/save/section/tax/" method="POST"> @@ -115,11 +131,15 @@ <field key="value">integer</field> </object> </object> - <object key="gift_wrapping" dataType="taxTotalFlagZero"> - <field key="value">integer</field> + <object key="gift_wrapping" dataType="tax_config_default"> + <object key="inherit" dataType="taxTotalFlagZero"> + <field key="value">integer</field> + </object> </object> - <object key="printed_card" dataType="taxTotalFlagZero"> - <field key="value">integer</field> + <object key="printed_card" dataType="tax_config_default"> + <object key="inherit" dataType="taxTotalFlagZero"> + <field key="value">integer</field> + </object> </object> <object key="grandtotal" dataType="tax_config_default"> <object key="inherit" dataType="taxTotalFlagZero"> @@ -155,11 +175,15 @@ <field key="value">integer</field> </object> </object> - <object key="gift_wrapping" dataType="taxTotalFlagZero"> - <field key="value">integer</field> + <object key="gift_wrapping" dataType="tax_config_default"> + <object key="inherit" dataType="taxTotalFlagZero"> + <field key="value">integer</field> + </object> </object> - <object key="printed_card" dataType="taxTotalFlagZero"> - <field key="value">integer</field> + <object key="printed_card" dataType="tax_config_default"> + <object key="inherit" dataType="taxTotalFlagZero"> + <field key="value">integer</field> + </object> </object> <object key="grandtotal" dataType="tax_config_default"> <object key="inherit" dataType="taxTotalFlagZero"> diff --git a/app/code/Magento/Tax/Test/Mftf/Page/CheckoutCartPage.xml b/app/code/Magento/Tax/Test/Mftf/Page/CheckoutCartPage.xml new file mode 100644 index 0000000000000..9b0b4fc537e1e --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/Page/CheckoutCartPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="CheckoutCartPage" url="/checkout/cart" module="Magento_Checkout" area="storefront"> + <section name="StorefrontCheckoutCartItemTaxSection"/> + </page> +</pages> diff --git a/app/code/Magento/Tax/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Tax/Test/Mftf/Section/CheckoutCartSummarySection.xml index b89a77b8ad2ca..da6528215887b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Tax/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -12,5 +12,7 @@ <element name="taxAmount" type="text" selector="[data-th='Tax']>span"/> <element name="taxSummary" type="text" selector=".totals-tax-summary"/> <element name="rate" type="text" selector=" tr.totals-tax-details.shown th.mark"/> + <element name="subtotalExcludingTax" type="text" selector="#cart-totals .totals.sub.excl span.price"/> + <element name="subtotalIncludingTax" type="text" selector="#cart-totals .totals.sub.incl span.price"/> </section> </sections> diff --git a/app/code/Magento/Tax/Test/Mftf/Section/StorefrontCheckoutCartItemTaxSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/StorefrontCheckoutCartItemTaxSection.xml new file mode 100644 index 0000000000000..c91a1fe4fb08b --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/Section/StorefrontCheckoutCartItemTaxSection.xml @@ -0,0 +1,15 @@ +<?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="StorefrontCheckoutCartItemTaxSection"> + <element name="productPriceExcludingTaxByName" type="text" selector="//a[contains(text(),'{{productName}}')]/ancestor::tr//td[contains(@class, 'price')]//span[contains(@class,'price-excluding-tax')]//span[contains(@class,'cart-tax-total')]" parameterized="true"/> + <element name="productSubtotalExcludingTaxByName" type="text" selector="//a[contains(text(),'{{productName}}')]/ancestor::tr//td[contains(@class, 'subtotal')]//span[contains(@class,'price-excluding-tax')]//span[contains(@class,'cart-tax-total')]" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml index dfed39e861f05..dce8852ac5628 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -59,7 +59,7 @@ <!-- Delete Tax Class --> <deleteData createDataKey="createProductTaxClass" stepKey="deleteProductTaxClass"/> <!--Logout--> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Create new order--> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="createNewOrder"> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxRulesNavigateMenuTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxRulesNavigateMenuTest.xml index 1277d6e5f9fd2..219cb309820d8 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxRulesNavigateMenuTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxRulesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresTaxRulesPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxZonesAndRatesNavigateMenuTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxZonesAndRatesNavigateMenuTest.xml index e0a4d5d9a4016..73c8c63be0318 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxZonesAndRatesNavigateMenuTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminStoresTaxZonesAndRatesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToStoresTaxZonesAndRatesPage"> <argument name="menuUiId" value="{{AdminMenuStores.dataUiId}}"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminSystemImportExportTaxRatesNavigateMenuTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminSystemImportExportTaxRatesNavigateMenuTest.xml index a84ae61d66305..2b2e0c5184d4a 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminSystemImportExportTaxRatesNavigateMenuTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminSystemImportExportTaxRatesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSystemImportExportTaxRatesPage"> <argument name="menuUiId" value="{{AdminMenuSystem.dataUiId}}"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml index fbf7873d37438..64d047c1a4dff 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml @@ -27,7 +27,7 @@ <createData entity="ApiSimpleProductWithCustomPrice" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="SetTaxClassForShippingActionGroup" stepKey="setTaxClass"/> <actionGroup ref="SetTaxApplyOnSettingActionGroup" stepKey="setApplyTaxOnSetting"> <argument name="userInput" value="Original price only"/> @@ -49,7 +49,7 @@ <argument name="userInput" value="Custom price if available"/> </actionGroup> <actionGroup ref="ResetTaxClassForShippingActionGroup" stepKey="resetTaxClassForShipping"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="NavigateToNewOrderPageNewCustomerSingleStoreActionGroup" stepKey="gotoNewOrderCreationPage"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxReportGridTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxReportGridTest.xml index e90602441261d..1611704c43334 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxReportGridTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxReportGridTest.xml @@ -219,7 +219,7 @@ <argument name="taxClassName" value="TaxClasses2"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml deleted file mode 100644 index 4b911cd6db32f..0000000000000 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml +++ /dev/null @@ -1,79 +0,0 @@ -<?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="StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest"> - <annotations> - <features value="Tax"/> - <stories value="Shopping cart taxes"/> - <title value="Tax information are updating/recalculating on fly in shopping cart for Guest (virtual quote)"/> - <description value="Tax information are updating/recalculating on fly in shopping cart for Guest (virtual quote)"/> - <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-41931"/> - <group value="checkout"/> - <group value="tax"/> - </annotations> - <before> - <!-- Preconditions --> - <!-- Tax Rule is created based on default tax rates (Stores>Tax Rule) US-CA-*-Rate 1 = 8.2500 US-NY-*-Rate 1 = 8.3750 --> - <createData entity="SimpleTaxRule" stepKey="createTaxRule"/> - <!-- Fixed Product Tax attribute is created and added to default attribute set --> - <createData entity="productFPTAttribute" stepKey="createProductFPTAttribute"/> - <createData entity="AddToDefaultSet" stepKey="addFPTToAttributeSet"> - <requiredEntity createDataKey="createProductFPTAttribute"/> - </createData> - <!-- Tax configuration (Store>Configuration; Sales>Tax) --> - <createData entity="Tax_Config_CA" stepKey="taxConfigurationCA"/> - <!-- Virtual product is created: Price = 10 --> - <createData entity="VirtualProduct" stepKey="createVirtualProduct"> - <field key="price">40.00</field> - </createData> - </before> - <after> - <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> - <deleteData createDataKey="createProductFPTAttribute" stepKey="deleteProductFPTAttribute"/> - <createData entity="DefaultTaxConfig" stepKey="defaultTaxConfiguration"/> - <deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProduct"/> - </after> - <!-- Test Steps --> - <!-- Step 1: Go to Storefront as Guest --> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <!-- Step 2: Add virtual product to shopping cart --> - <amOnPage url="{{StorefrontProductPage.url($$createVirtualProduct.name$$)}}" stepKey="amOnStorefrontVirtualProductPage"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="cartAddVirtualProductToCart"> - <argument name="product" value="$$createVirtualProduct$$"/> - <argument name="productCount" value="1"/> - </actionGroup> - <!-- Step 3: Go to Shopping Cart --> - <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> - <!-- Step 4: Open Estimate Shipping and Tax section --> - <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingandTax" /> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUSCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="California" stepKey="selectCaliforniaRegion"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$3.30" stepKey="checkTaxAmountCA" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary"/> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-CA-*-Rate 1 (8.25%)" stepKey="checkRateCA" /> - <!-- Step 5: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Switzerland" stepKey="selectSwitzerlandCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Aargau" stepKey="selectAargauRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="1234" stepKey="inputPostCode"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmount" /> - <!-- Step 6: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUnitedStatesCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="New York" stepKey="selectNewYorkRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="12345" stepKey="inputPostCode2"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary2" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary2"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$3.35" stepKey="checkTaxAmountNY" /> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-NY-*-Rate 1 (8.375%)" stepKey="checkRateNY" /> - </test> -</tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml index f0fac38a6c05c..3d584f988780e 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml @@ -41,13 +41,14 @@ </actionGroup> <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!-- Fill out form for a new user with address --> <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> <argument name="Customer" value="Simple_US_Customer_NY"/> </actionGroup> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddressInfo"> <argument name="Address" value="US_Address_NY"/> </actionGroup> </before> @@ -165,7 +166,7 @@ <argument name="Customer" value="Simple_US_Customer_NY"/> </actionGroup> - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <actionGroup ref="EnterCustomerAddressInfoActionGroup" stepKey="enterAddressInfo"> <argument name="Address" value="US_Address_NY"/> </actionGroup> </before> @@ -275,6 +276,8 @@ </actionGroup> <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> @@ -385,6 +388,8 @@ </actionGroup> <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml index e0e411a04d484..050ab3889984b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml @@ -41,6 +41,8 @@ </actionGroup> <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> @@ -146,14 +148,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <!-- Fill out form for a new user with address --> - <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> - <argument name="Customer" value="Simple_US_Customer_NY"/> - </actionGroup> - - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> - <argument name="Address" value="US_Address_NY"/> - </actionGroup> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> @@ -186,6 +181,15 @@ <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> </after> + <!-- Fill out form for a new user with address --> + <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> + <argument name="Customer" value="Simple_US_Customer_NY"/> + </actionGroup> + + <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <argument name="Address" value="US_Address_NY"/> + </actionGroup> + <!-- Go to the created product page and add it to the cart --> <amOnPage url="$$simpleProduct1.sku$$.html" stepKey="goToSimpleProductPage"/> <waitForPageLoad stepKey="waitForSimpleProductPage"/> @@ -265,6 +269,8 @@ </actionGroup> <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> @@ -381,14 +387,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <!-- Fill out form for a new user with address --> - <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> - <argument name="Customer" value="Simple_US_Customer_NY"/> - </actionGroup> - - <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> - <argument name="Address" value="US_Address_NY"/> - </actionGroup> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Go to the tax rule page and delete the row we created--> @@ -421,6 +420,15 @@ <deleteData createDataKey="virtualProduct1" stepKey="deleteVirtualProduct1"/> </after> + <!-- Fill out form for a new user with address --> + <actionGroup ref="SignUpNewUserFromStorefrontActionGroup" stepKey="SignUpNewUser"> + <argument name="Customer" value="Simple_US_Customer_NY"/> + </actionGroup> + + <actionGroup ref="EnterCustomerAddressInfo" stepKey="enterAddressInfo"> + <argument name="Address" value="US_Address_NY"/> + </actionGroup> + <!-- Go to the created product page and add it to the cart --> <amOnPage url="$$virtualProduct1.sku$$.html" stepKey="goToVirtualProductPage"/> <waitForPageLoad stepKey="waitForVirtualProductPage"/> diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index a3f054d7c8dc7..70ea478004b9d 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -58,9 +58,9 @@ function ($matches) use (&$cssMatches) { } $media = $media ?? 'all'; $loadCssAsync = sprintf( - '<link rel="preload" as="style" media="%s" . - onload="this.onload=null;this.rel=\'stylesheet\'"' . - 'href="%s">', + '<link rel="preload" as="style" media="%s"' . + ' onload="this.onload=null;this.rel=\'stylesheet\'"' . + ' href="%s" />', $media, $href ); diff --git a/app/code/Magento/Theme/Model/Theme/ThemePackageInfo.php b/app/code/Magento/Theme/Model/Theme/ThemePackageInfo.php index 1a5da09a7a4e7..f98fe3d76a35e 100644 --- a/app/code/Magento/Theme/Model/Theme/ThemePackageInfo.php +++ b/app/code/Magento/Theme/Model/Theme/ThemePackageInfo.php @@ -67,7 +67,7 @@ public function getPackageName($themePath) if ($themeFile) { $rawData = $this->serializer->unserialize($themeFile); } - return isset($rawData['name']) ? $rawData['name'] : ''; + return $rawData['name'] ?? ''; } return ''; } @@ -83,8 +83,7 @@ public function getFullThemePath($packageName) if (empty($this->packageNameToFullPathMap)) { $this->initializeMap(); } - return isset($this->packageNameToFullPathMap[$packageName]) - ? $this->packageNameToFullPathMap[$packageName] : ''; + return $this->packageNameToFullPathMap[$packageName] ?? ''; } /** diff --git a/app/code/Magento/Theme/Test/Mftf/Section/AdminDesignConfigSection.xml b/app/code/Magento/Theme/Test/Mftf/Section/AdminDesignConfigSection.xml index 762537ba426f2..820917661b2ce 100644 --- a/app/code/Magento/Theme/Test/Mftf/Section/AdminDesignConfigSection.xml +++ b/app/code/Magento/Theme/Test/Mftf/Section/AdminDesignConfigSection.xml @@ -26,6 +26,9 @@ <element name="logoUpload" type ="input" selector="[name='email_logo']" /> <element name="logoWrapperOpen" type ="text" selector="[data-index='email'] [data-state-collapsible ='closed']"/> <element name="logoPreview" type ="text" selector="[alt ='magento-logo.png']"/> + <element name="logoImageAlt" type ="text" selector="[name='email_logo_alt']"/> + <element name="logoImageWidth" type ="text" selector="[name='email_logo_width']"/> + <element name="logoImageHeight" type ="text" selector="[name='email_logo_height']"/> <element name="faviconArrow" type="button" selector="#ZmF2aWNvbg-- > .jstree-icon" /> <element name="checkIfFaviconArrowExpand" type="button" selector="//li[@id='ZmF2aWNvbg--' and contains(@class,'jstree-closed')]" /> <element name="storesArrow" type="button" selector="#ZmF2aWNvbi9zdG9yZXM- > .jstree-icon" /> @@ -34,5 +37,7 @@ <element name="imageWatermarkType" type="text" selector="//div[contains(@class, 'fieldset-wrapper-title')]//span[contains(text(), '{{watermarkType}}')]" parameterized="true"/> <element name="appliedTheme" type="select" selector="select[name='theme_theme_id']"/> <element name="scopeEditLinkByName" type="button" selector="//tr//td[count(//div[@data-role='grid-wrapper']//tr//th[normalize-space(.)= '{{scope}}']/preceding-sibling::th)+1][contains(.,'{{scopeName}}')]/..//a[contains(@class, 'action-menu-item')]" timeout="30" parameterized="true"/> + <element name="transactionalEmailSectionHeader" type="button" selector="[data-index='email'] .fieldset-wrapper-title" timeout="30"/> + <element name="transactionalEmailSectionBody" type="block" selector="[data-index='email'] .admin__fieldset-wrapper-content" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemeSortTest.xml b/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemeSortTest.xml index 9facab57e9a09..4a074a484537d 100644 --- a/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemeSortTest.xml +++ b/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemeSortTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToContentThemesPage"> <argument name="menuUiId" value="{{AdminMenuContent.dataUiId}}"/> diff --git a/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemesNavigateMenuTest.xml b/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemesNavigateMenuTest.xml index 8e7bfd71b07d3..2d0dc4501dfa1 100644 --- a/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemesNavigateMenuTest.xml +++ b/app/code/Magento/Theme/Test/Mftf/Test/AdminContentThemesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToContentThemesPage"> <argument name="menuUiId" value="{{AdminMenuContent.dataUiId}}"/> diff --git a/app/code/Magento/Theme/Test/Mftf/Test/AdminDesignConfigMediaGalleryImageUploadTest.xml b/app/code/Magento/Theme/Test/Mftf/Test/AdminDesignConfigMediaGalleryImageUploadTest.xml index 8291ddc12b3b1..ae0ebe2ed7ef3 100644 --- a/app/code/Magento/Theme/Test/Mftf/Test/AdminDesignConfigMediaGalleryImageUploadTest.xml +++ b/app/code/Magento/Theme/Test/Mftf/Test/AdminDesignConfigMediaGalleryImageUploadTest.xml @@ -22,7 +22,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Edit Store View--> <comment userInput="Edit Store View" stepKey="editStoreViewComment"/> diff --git a/app/code/Magento/Theme/Test/Mftf/Test/AdminWatermarkUploadTest.xml b/app/code/Magento/Theme/Test/Mftf/Test/AdminWatermarkUploadTest.xml index afe70243f602c..666d01e1090c1 100644 --- a/app/code/Magento/Theme/Test/Mftf/Test/AdminWatermarkUploadTest.xml +++ b/app/code/Magento/Theme/Test/Mftf/Test/AdminWatermarkUploadTest.xml @@ -25,7 +25,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <amOnPage url="{{DesignConfigPage.url}}" stepKey="navigateToDesignConfigPage" /> <waitForPageLoad stepKey="waitForPageload1"/> diff --git a/app/code/Magento/Theme/Test/Mftf/Test/ThemeTest.xml b/app/code/Magento/Theme/Test/Mftf/Test/ThemeTest.xml index 67213934a6c41..56041c6ccc99a 100644 --- a/app/code/Magento/Theme/Test/Mftf/Test/ThemeTest.xml +++ b/app/code/Magento/Theme/Test/Mftf/Test/ThemeTest.xml @@ -19,7 +19,7 @@ <group value="Theme"/> </annotations> <after> - <actionGroup ref="logout" stepKey="logoutOfAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> <!--Login to Admin Area--> <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminArea"/> diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php new file mode 100644 index 0000000000000..b1303e991a680 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -0,0 +1,145 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\Test\Unit\Controller\Result; + +use Magento\Theme\Controller\Result\AsyncCssPlugin; +use Magento\Framework\App\Response\Http; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for Magento\Theme\Test\Unit\Controller\Result\AsyncCssPlugin. + */ +class AsyncCssPluginTest extends TestCase +{ + const STUB_XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + + /** + * @var AsyncCssPlugin + */ + private $plugin; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Http|MockObject + */ + private $httpMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->setMethods(['isSetFlag']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->httpMock = $this->createMock(Http::class); + + $objectManager = new ObjectManagerHelper($this); + $this->plugin = $objectManager->getObject( + AsyncCssPlugin::class, + [ + 'scopeConfig' => $this->scopeConfigMock + ] + ); + } + + /** + * Data Provider for before send response + * + * @return array + */ + public function sendResponseDataProvider(): array + { + return [ + [ + "content" => "<body><h1>Test Title</h1>" . + "<link rel=\"stylesheet\" href=\"css/critical.css\" />" . + "<p>Test Content</p></body>", + "flag" => true, + "result" => "<body><h1>Test Title</h1>" . + "<link rel=\"preload\" as=\"style\" media=\"all\"" . + " onload=\"this.onload=null;this.rel='stylesheet'\" href=\"css/critical.css\" />" . + "<p>Test Content</p>" . + "<link rel=\"stylesheet\" href=\"css/critical.css\" />" . + "\n</body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => false, + "result" => "<body><p>Test Content</p></body>" + ], + [ + "content" => "<body><p>Test Content</p></body>", + "flag" => true, + "result" => "<body><p>Test Content</p></body>" + ] + ]; + } + + /** + * Test beforeSendResponse + * + * @param string $content + * @param bool $isSetFlag + * @param string $result + * @return void + * @dataProvider sendResponseDataProvider + */ + public function testBeforeSendResponse($content, $isSetFlag, $result): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn($content); + + $this->scopeConfigMock->expects($this->once()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, + ScopeInterface::SCOPE_STORE + ) + ->willReturn($isSetFlag); + + $this->httpMock->expects($this->any()) + ->method('setContent') + ->with($result); + + $this->plugin->beforeSendResponse($this->httpMock); + } + + /** + * Test BeforeSendResponse if content is not a string + * + * @return void + */ + public function testIfGetContentIsNotAString(): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn([]); + + $this->scopeConfigMock->expects($this->any()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, + ScopeInterface::SCOPE_STORE + ) + ->willReturn(false); + + $this->plugin->beforeSendResponse($this->httpMock); + } +} diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php new file mode 100644 index 0000000000000..8b696251d4e73 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\Test\Unit\Controller\Result; + +use Magento\Theme\Controller\Result\JsFooterPlugin; +use Magento\Framework\App\Response\Http; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for Magento\Theme\Test\Unit\Controller\Result\JsFooterPlugin. + */ +class JsFooterPluginTest extends TestCase +{ + const STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM = 'dev/js/move_script_to_bottom'; + + /** + * @var JsFooterPlugin + */ + private $plugin; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $scopeConfigMock; + + /** + * @var Http|MockObject + */ + private $httpMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->setMethods(['isSetFlag']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->httpMock = $this->createMock(Http::class); + + $objectManager = new ObjectManagerHelper($this); + $this->plugin = $objectManager->getObject( + JsFooterPlugin::class, + [ + 'scopeConfig' => $this->scopeConfigMock + ] + ); + } + + /** + * Data Provider for testBeforeSendResponse() + * + * @return array + */ + public function sendResponseDataProvider(): array + { + return [ + 'content_with_script_tag' => [ + "content" => "<body><h1>Test Title</h1>" . + "<script type=\"text/x-magento-init\">test</script>" . + "<script type=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p></body>", + "flag" => true, + "result" => "<body><h1>Test Title</h1>" . + "<script type=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p>" . + "<script type=\"text/x-magento-init\">test</script>" . + "\n</body>" + ], + 'content_with_config_disable' => [ + "content" => "<body><p>Test Content</p></body>", + "flag" => false, + "result" => "<body><p>Test Content</p></body>" + ], + 'content_without_script_tag' => [ + "content" => "<body><p>Test Content</p></body>", + "flag" => true, + "result" => "<body><p>Test Content</p>\n</body>" + ] + ]; + } + + /** + * Test beforeSendResponse + * + * @param string $content + * @param bool $isSetFlag + * @param string $result + * @return void + * @dataProvider sendResponseDataProvider + */ + public function testBeforeSendResponse($content, $isSetFlag, $result): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn($content); + + $this->scopeConfigMock->expects($this->once()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ->willReturn($isSetFlag); + + $this->httpMock->expects($this->any()) + ->method('setContent') + ->with($result); + + $this->plugin->beforeSendResponse($this->httpMock); + } + + /** + * Data Provider for testBeforeSendResponseIfGetContentIsNotAString() + * + * @return array + */ + public function ifGetContentIsNotAStringDataProvider(): array + { + return [ + 'empty_array' => [ + 'content' => [] + ], + 'null' => [ + 'content' => null + ] + ]; + } + + /** + * Test BeforeSendResponse if content is not a string + * + * @param string $content + * @return void + * @dataProvider ifGetContentIsNotAStringDataProvider + */ + public function testBeforeSendResponseIfGetContentIsNotAString($content): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn($content); + + $this->scopeConfigMock->expects($this->never()) + ->method('isSetFlag') + ->with( + self::STUB_XML_PATH_DEV_MOVE_JS_TO_BOTTOM, + ScopeInterface::SCOPE_STORE + ) + ->willReturn(false); + + $this->plugin->beforeSendResponse($this->httpMock); + } +} diff --git a/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml b/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml index deb94a7f30d34..9c4e7bf3a646a 100644 --- a/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml +++ b/app/code/Magento/Tinymce3/Test/Mftf/Test/AdminSwitchWYSIWYGOptionsTest.xml @@ -19,7 +19,7 @@ <testCaseId value="MC-6114"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginGetFromGeneralFile"/> <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> </before> <amOnPage url="{{ConfigurationStoresPage.url}}" stepKey="navigateToWYSIWYGConfigPage1"/> @@ -81,7 +81,7 @@ <actionGroup ref="SwitchToVersion4ActionGroup" stepKey="switchToTinyMCE4" /> <after> <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> </test> </tests> diff --git a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js index 8170e4ed44eea..512f3520f2ef0 100644 --- a/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js +++ b/app/code/Magento/Tinymce3/view/base/web/tiny_mce/plugins/table/editor_plugin_src.js @@ -1222,7 +1222,7 @@ var last; // Skip empty text nodes form the end - for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ; + for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling); if (last && last.nodeName == 'TABLE') ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />'); diff --git a/app/code/Magento/Translation/Test/Mftf/Test/AdminInlineTranslationOnCheckoutTest.xml b/app/code/Magento/Translation/Test/Mftf/Test/AdminInlineTranslationOnCheckoutTest.xml index 08448f7735f7c..c6f2bb0713f48 100644 --- a/app/code/Magento/Translation/Test/Mftf/Test/AdminInlineTranslationOnCheckoutTest.xml +++ b/app/code/Magento/Translation/Test/Mftf/Test/AdminInlineTranslationOnCheckoutTest.xml @@ -43,7 +43,7 @@ <deleteData createDataKey="createCustomer3" stepKey="deleteCustomer3"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <!-- Set production mode --> <!-- <magentoCLI command="cache:flush" stepKey="flushCache"/>--> diff --git a/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php b/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php index 146e1c06782ce..be52c6a744c50 100644 --- a/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php +++ b/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php @@ -3,72 +3,79 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Translation\Test\Unit\Model\Js; use Magento\Framework\App\State; use Magento\Framework\App\Utility\Files; -use Magento\Framework\Filesystem; +use Magento\Framework\Component\ComponentRegistrar; +use Magento\Framework\Component\DirSearch; +use Magento\Framework\Filesystem\File\Read; +use Magento\Framework\Filesystem\File\ReadFactory; use Magento\Framework\Filesystem\File\ReadInterface; -use Magento\Translation\Model\Js\DataProvider; -use Magento\Translation\Model\Js\Config; use Magento\Framework\Phrase\Renderer\Translate; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Translation\Model\Js\Config; +use Magento\Translation\Model\Js\DataProvider as ModelDataProvider; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Verify data provider translation * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class DataProviderTest extends \PHPUnit\Framework\TestCase +class DataProviderTest extends TestCase { /** - * @var DataProvider + * @var ModelDataProvider */ - protected $model; + private $model; /** - * @var State|\PHPUnit_Framework_MockObject_MockObject + * @var State|MockObject */ - protected $appStateMock; + private $appStateMock; /** - * @var Config|\PHPUnit_Framework_MockObject_MockObject + * @var Config|MockObject */ - protected $configMock; + private $configMock; /** - * @var Files|\PHPUnit_Framework_MockObject_MockObject + * @var Files|MockObject */ - protected $filesUtilityMock; + private $filesUtilityMock; /** - * @var ReadInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ReadInterface|MockObject */ - protected $fileReadMock; + private $fileReadMock; /** - * @var Translate|\PHPUnit_Framework_MockObject_MockObject + * @var Translate|MockObject */ - protected $translateMock; + private $translateMock; /** - * @return void + * @inheritDoc */ protected function setUp() { - $this->appStateMock = $this->createMock(\Magento\Framework\App\State::class); - $this->configMock = $this->createMock(\Magento\Translation\Model\Js\Config::class); - $this->filesUtilityMock = $this->createMock(\Magento\Framework\App\Utility\Files::class); - $fileReadFactory = $this->createMock(\Magento\Framework\Filesystem\File\ReadFactory::class); - $this->fileReadMock = $this->createMock(\Magento\Framework\Filesystem\File\Read::class); - $this->translateMock = $this->createMock(\Magento\Framework\Phrase\Renderer\Translate::class); + $this->appStateMock = $this->createMock(State::class); + $this->configMock = $this->createMock(Config::class); + $this->filesUtilityMock = $this->createMock(Files::class); + $fileReadFactory = $this->createMock(ReadFactory::class); + $this->fileReadMock = $this->createMock(Read::class); + $this->translateMock = $this->createMock(Translate::class); $fileReadFactory->expects($this->atLeastOnce()) ->method('create') ->willReturn($this->fileReadMock); - $dirSearch = $this->createMock(\Magento\Framework\Component\DirSearch::class); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $dirSearch = $this->createMock(DirSearch::class); + $objectManager = new ObjectManager($this); $this->model = $objectManager->getObject( - \Magento\Translation\Model\Js\DataProvider::class, + ModelDataProvider::class, [ 'appState' => $this->appStateMock, 'config' => $this->configMock, @@ -76,16 +83,19 @@ protected function setUp() 'translate' => $this->translateMock, 'dirSearch' => $dirSearch, 'filesUtility' => $this->filesUtilityMock, - 'componentRegistrar' => - $this->createMock(\Magento\Framework\Component\ComponentRegistrar::class) + 'componentRegistrar' => $this->createMock(ComponentRegistrar::class) ] ); } /** + * Verify data translate. + * + * @param array $config * @return void + * @dataProvider configDataProvider */ - public function testGetData() + public function testGetData(array $config): void { $themePath = 'blank'; $areaCode = 'adminhtml'; @@ -101,36 +111,6 @@ public function testGetData() [$areaCode, $themePath, '*', '*', [$filePaths[3]]] ]; - $expectedResult = [ - 'hello1' => 'hello1translated', - 'hello2' => 'hello2translated', - 'hello3' => 'hello3translated', - 'hello4' => 'hello4translated', - 'ko i18' => 'ko i18 translated', - 'underscore i18' => 'underscore i18 translated', - ]; - - $contentsMap = [ - 'content1$.mage.__("hello1")content1', - 'content2$.mage.__("hello2")content2', - 'content2$.mage.__("hello4")content4 <!-- ko i18n: "ko i18" --><!-- /ko -->', - 'content2$.mage.__("hello3")content3 <% _.i18n("underscore i18") %>', - ]; - - $translateMap = [ - [['hello1'], [], 'hello1translated'], - [['hello2'], [], 'hello2translated'], - [['hello3'], [], 'hello3translated'], - [['hello4'], [], 'hello4translated'], - [['ko i18'], [], 'ko i18 translated'], - [['underscore i18'], [], 'underscore i18 translated'], - ]; - - $patterns = [ - '~\$\.mage\.__\(([\'"])(.+?)\1\)~', - '~(?:i18n\:|_\.i18n\()\s*(["\'])(.*?)(?<!\\\\)\1~', - ]; - $this->appStateMock->expects($this->once()) ->method('getAreaCode') ->willReturn($areaCode); @@ -141,7 +121,7 @@ public function testGetData() ->method('getStaticHtmlFiles') ->willReturnMap($staticFilesMap); - foreach ($contentsMap as $index => $content) { + foreach ($config['contentsMap'] as $index => $content) { $this->fileReadMock->expects($this->at($index)) ->method('readAll') ->willReturn($content); @@ -149,34 +129,37 @@ public function testGetData() $this->configMock->expects($this->any()) ->method('getPatterns') - ->willReturn($patterns); + ->willReturn($config['patterns']); $this->translateMock->expects($this->any()) ->method('render') - ->willReturnMap($translateMap); + ->willReturnMap($config['translateMap']); $actualResult = $this->model->getData($themePath); - $this->assertEquals($expectedResult, $actualResult); + $this->assertEquals($config['expectedResult'], $actualResult); $this->assertEquals( - json_encode($expectedResult), + json_encode($config['expectedResult']), json_encode($actualResult), "Translations should be sorted by key" ); } /** + * Verify get data throwing exception. + * + * @param array $config + * @return void + * @dataProvider configDataProvider * @expectedException \Magento\Framework\Exception\LocalizedException */ - public function testGetDataThrowingException() + public function testGetDataThrowingException(array $config): void { $themePath = 'blank'; $areaCode = 'adminhtml'; - - $patterns = ['~\$\.mage\.__\(([\'"])(.+?)\1\)~']; + $patterns = $config['patterns']; $this->fileReadMock->expects($this->once()) ->method('readAll') ->willReturn('content1$.mage.__("hello1")content1'); - $this->appStateMock->expects($this->once()) ->method('getAreaCode') ->willReturn($areaCode); @@ -186,15 +169,57 @@ public function testGetDataThrowingException() $this->filesUtilityMock->expects($this->any()) ->method('getStaticHtmlFiles') ->willReturn(['test']); - $this->configMock->expects($this->any()) ->method('getPatterns') ->willReturn($patterns); - $this->translateMock->expects($this->once()) ->method('render') ->willThrowException(new \Exception('Test exception')); $this->model->getData($themePath); } + + /** + * Config data provider. + * + * @return array + */ + public function configDataProvider(): array + { + return [ + [ + [ + 'patterns' => [ + '~\$\.mage\.__\(([\'"])(.+?)\1\)~', + '~(?:i18n\:|_\.i18n\()\s*(["\'])(.*?)(?<!\\\\)\1~', + '~translate\=("\')([^\'].*?)\'\"~', + '~(?s)\$t\(\s*([\'"])(\?\<translate\>.+?)(?<!\\\)\1\s*(*SKIP)\)(?s)~', + '~translate args\=("|\'|"\'|\\\"\')([^\'].*?)(\'\\\"|\'"|\'|")~', + ], + 'expectedResult' => [ + 'hello1' => 'hello1translated', + 'hello2' => 'hello2translated', + 'hello3' => 'hello3translated', + 'hello4' => 'hello4translated', + 'ko i18' => 'ko i18 translated', + 'underscore i18' => 'underscore i18 translated', + ], + 'contentsMap' => [ + 'content1$.mage.__("hello1")content1', + 'content2$.mage.__("hello2")content2', + 'content2$.mage.__("hello4")content4 <!-- ko i18n: "ko i18" --><!-- /ko -->', + 'content2$.mage.__("hello3")content3 <% _.i18n("underscore i18") %>', + ], + 'translateMap' => [ + [['hello1'], [], 'hello1translated'], + [['hello2'], [], 'hello2translated'], + [['hello3'], [], 'hello3translated'], + [['hello4'], [], 'hello4translated'], + [['ko i18'], [], 'ko i18 translated'], + [['underscore i18'], [], 'underscore i18 translated'], + ] + ], + ] + ]; + } } diff --git a/app/code/Magento/Translation/etc/di.xml b/app/code/Magento/Translation/etc/di.xml index de476f52a53fe..783384fe64fa9 100644 --- a/app/code/Magento/Translation/etc/di.xml +++ b/app/code/Magento/Translation/etc/di.xml @@ -68,7 +68,7 @@ <item name="translate_wrapping" xsi:type="string"><![CDATA[~translate\=("')([^\'].*?)\'\"~]]></item> <item name="mage_translation_widget" xsi:type="string"><![CDATA[~(?s)(?:\$|jQuery)\.mage\.__\(\s*(['"])(?<translate>.+?)(?<!\\)\1\s*(*SKIP)\)\s*(?s)~]]></item> <item name="mage_translation_static" xsi:type="string"><![CDATA[~(?s)\$t\(\s*(['"])(?<translate>.+?)(?<!\\)\1\s*(*SKIP)\)(?s)~]]></item> - <item name="translate_args" xsi:type="string"><![CDATA[~translate args\=("|'|"')([^\'].*?)('"|'|")~]]></item> + <item name="translate_args" xsi:type="string"><![CDATA[~translate args\=("|'|"'|\\"')([^\'].*?)('\\"|'"|'|")~]]></item> </argument> </arguments> </type> diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index 772bdceeb4957..9ce6d7d7fd334 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -5,15 +5,14 @@ */ namespace Magento\Ui\Component; +use Magento\Framework\Data\ValueSourceInterface; use Magento\Framework\DataObject; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Framework\View\Element\UiComponentInterface; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\DataSourceInterface; use Magento\Framework\View\Element\UiComponent\ObserverInterface; -use Magento\Framework\Data\ValueSourceInterface; +use Magento\Framework\View\Element\UiComponentInterface; +//phpcs:disable Magento2.Classes.AbstractApi /** * Abstract class AbstractComponent * @@ -146,7 +145,7 @@ protected function prepareChildComponent(UiComponentInterface $component) */ public function toHtml() { - $this->render(); + return $this->render(); } /** @@ -173,12 +172,14 @@ public function addComponent($name, UiComponentInterface $component) } /** + * Return component + * * @param string $name * @return UiComponentInterface */ public function getComponent($name) { - return isset($this->components[$name]) ? $this->components[$name] : null; + return $this->components[$name] ?? null; } /** @@ -242,6 +243,7 @@ public function getJsConfig(UiComponentInterface $component) return $jsConfig; } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Component data setter * @@ -254,6 +256,7 @@ public function setData($key, $value = null) parent::setData($key, $value); } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Component data getter * @@ -278,7 +281,7 @@ public function prepareDataSource(array $dataSource) } /** - * {@inheritdoc} + * @inheritdoc */ public function getDataSourceData() { diff --git a/app/code/Magento/Ui/Component/MassAction/Filter.php b/app/code/Magento/Ui/Component/MassAction/Filter.php index c512c82d694bc..a06592bbd6758 100644 --- a/app/code/Magento/Ui/Component/MassAction/Filter.php +++ b/app/code/Magento/Ui/Component/MassAction/Filter.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Ui\Component\MassAction; @@ -107,7 +108,7 @@ public function getCollection(AbstractDb $collection) $filterIds = array_unique(array_merge($filterIds, $selected)); } $collection->addFieldToFilter( - $collection->getIdFieldName(), + $collection->getResource()->getIdFieldName(), ['in' => $filterIds] ); @@ -163,9 +164,9 @@ protected function applySelection(AbstractDb $collection) try { if (is_array($excluded) && !empty($excluded)) { - $collection->addFieldToFilter($collection->getIdFieldName(), ['nin' => $excluded]); + $collection->addFieldToFilter($collection->getResource()->getIdFieldName(), ['nin' => $excluded]); } elseif (is_array($selected) && !empty($selected)) { - $collection->addFieldToFilter($collection->getIdFieldName(), ['in' => $selected]); + $collection->addFieldToFilter($collection->getResource()->getIdFieldName(), ['in' => $selected]); } else { throw new LocalizedException(__('An item needs to be selected. Select and try again.')); } diff --git a/app/code/Magento/Ui/Config/Reader/Definition/Data.php b/app/code/Magento/Ui/Config/Reader/Definition/Data.php index 62bb07a6486f5..44b2c87e544a2 100644 --- a/app/code/Magento/Ui/Config/Reader/Definition/Data.php +++ b/app/code/Magento/Ui/Config/Reader/Definition/Data.php @@ -17,14 +17,8 @@ */ class Data implements \Magento\Framework\Config\DataInterface { - /** - * ID in the storage cache - */ const CACHE_ID = 'ui_component_configuration_definition_data'; - /** - * Search pattern - */ const SEARCH_PATTERN = '%s.xml'; /** @@ -123,7 +117,7 @@ public function merge(array $config) */ public function get($key, $default = null) { - return isset($this->data[$key]) ? $this->data[$key] : $default; + return $this->data[$key] ?? $default; } /** diff --git a/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php b/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php index 578ebe4d441d9..abbc79859a038 100644 --- a/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php +++ b/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php @@ -8,7 +8,10 @@ use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; + // phpcs:disable Magento2.Classes.AbstractApi /** + * @inheritdoc + * * @api * @since 100.0.2 */ @@ -74,6 +77,8 @@ public function __construct( } /** + * Return collection + * * @return AbstractCollection */ public function getCollection() @@ -112,6 +117,8 @@ public function getRequestFieldName() } /** + * Return Meta + * * @return array */ public function getMeta() @@ -127,28 +134,30 @@ public function getMeta() */ public function getFieldSetMetaInfo($fieldSetName) { - return isset($this->meta[$fieldSetName]) ? $this->meta[$fieldSetName] : []; + return $this->meta[$fieldSetName] ?? []; } /** + * Return fields meta info + * * @param string $fieldSetName * @return array */ public function getFieldsMetaInfo($fieldSetName) { - return isset($this->meta[$fieldSetName]['children']) ? $this->meta[$fieldSetName]['children'] : []; + return $this->meta[$fieldSetName]['children'] ?? []; } /** + * Return field meta info + * * @param string $fieldSetName * @param string $fieldName * @return array */ public function getFieldMetaInfo($fieldSetName, $fieldName) { - return isset($this->meta[$fieldSetName]['children'][$fieldName]) - ? $this->meta[$fieldSetName]['children'][$fieldName] - : []; + return $this->meta[$fieldSetName]['children'][$fieldName] ?? []; } /** @@ -197,7 +206,7 @@ public function addField($field, $alias = null) } /** - * self::setOrder() alias + * Alias for self::setOrder() * * @param string $field * @param string $direction @@ -270,7 +279,7 @@ public function count() */ public function getConfigData() { - return isset($this->data['config']) ? $this->data['config'] : []; + return $this->data['config'] ?? []; } /** diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index 3f6685e37fcc4..59f3af18de451 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -3,19 +3,28 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Ui\Model\Export; +use DateTime; +use DateTimeZone; +use Exception; use Magento\Framework\Api\Search\DocumentInterface; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Framework\View\Element\UiComponentInterface; use Magento\Ui\Component\Filters; use Magento\Ui\Component\Filters\Type\Select; use Magento\Ui\Component\Listing\Columns; +use Magento\Ui\Component\Listing\Columns\Column; use Magento\Ui\Component\MassAction\Filter; -use Magento\Framework\Locale\ResolverInterface; -use Magento\Framework\Stdlib\DateTime\TimezoneInterface; /** - * Metadata Provider + * Metadata Provider for grid listing export. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class MetadataProvider @@ -75,26 +84,29 @@ public function __construct( * Returns Columns component * * @param UiComponentInterface $component + * * @return UiComponentInterface - * @throws \Exception + * @throws Exception */ - protected function getColumnsComponent(UiComponentInterface $component) + protected function getColumnsComponent(UiComponentInterface $component): UiComponentInterface { foreach ($component->getChildComponents() as $childComponent) { if ($childComponent instanceof Columns) { return $childComponent; } } - throw new \Exception('No columns found'); // @codingStandardsIgnoreLine + throw new Exception('No columns found'); // @codingStandardsIgnoreLine } /** * Returns columns list * * @param UiComponentInterface $component + * * @return UiComponentInterface[] + * @throws Exception */ - protected function getColumns(UiComponentInterface $component) + protected function getColumns(UiComponentInterface $component): array { if (!isset($this->columns[$component->getName()])) { $columns = $this->getColumnsComponent($component); @@ -104,6 +116,7 @@ protected function getColumns(UiComponentInterface $component) } } } + return $this->columns[$component->getName()]; } @@ -111,9 +124,11 @@ protected function getColumns(UiComponentInterface $component) * Retrieve Headers row array for Export * * @param UiComponentInterface $component + * * @return string[] + * @throws Exception */ - public function getHeaders(UiComponentInterface $component) + public function getHeaders(UiComponentInterface $component): array { $row = []; foreach ($this->getColumns($component) as $column) { @@ -127,14 +142,17 @@ public function getHeaders(UiComponentInterface $component) * Returns DB fields list * * @param UiComponentInterface $component - * @return array + * + * @return string[] + * @throws Exception */ - public function getFields(UiComponentInterface $component) + public function getFields(UiComponentInterface $component): array { $row = []; foreach ($this->getColumns($component) as $column) { $row[] = $column->getName(); } + return $row; } @@ -144,9 +162,10 @@ public function getFields(UiComponentInterface $component) * @param DocumentInterface $document * @param array $fields * @param array $options - * @return array + * + * @return string[] */ - public function getRowData(DocumentInterface $document, $fields, $options) + public function getRowData(DocumentInterface $document, $fields, $options): array { $row = []; foreach ($fields as $column) { @@ -155,12 +174,13 @@ public function getRowData(DocumentInterface $document, $fields, $options) if (isset($options[$column][$key])) { $row[] = $options[$column][$key]; } else { - $row[] = ''; + $row[] = $key; } } else { $row[] = $document->getCustomAttribute($column)->getValue(); } } + return $row; } @@ -170,9 +190,10 @@ public function getRowData(DocumentInterface $document, $fields, $options) * @param array $list * @param string $label * @param array $output + * * @return void */ - protected function getComplexLabel($list, $label, &$output) + protected function getComplexLabel($list, $label, &$output): void { foreach ($list as $item) { if (!is_array($item['value'])) { @@ -184,34 +205,75 @@ protected function getComplexLabel($list, $label, &$output) } /** - * Returns array of Select options + * Prepare array of options. + * + * @param array $options * - * @param Select $filter * @return array */ - protected function getFilterOptions(Select $filter) + protected function getOptionsArray(array $options): array { - $options = []; - foreach ($filter->getData('config/options') as $option) { + $preparedOptions = []; + foreach ($options as $option) { if (!is_array($option['value'])) { - $options[$option['value']] = $option['label']; + $preparedOptions[$option['value']] = $option['label']; } else { $this->getComplexLabel( $option['value'], $option['label'], - $options + $preparedOptions ); } } - return $options; + + return $preparedOptions; } /** * Returns Filters with options * * @return array + * @throws LocalizedException */ - public function getOptions() + public function getOptions(): array + { + return array_merge( + $this->getColumnOptions(), + $this->getFilterOptions() + ); + } + + /** + * Get options from columns. + * + * @return array + * @throws LocalizedException + * @throws Exception + */ + protected function getColumnOptions(): array + { + $options = []; + $component = $this->filter->getComponent(); + /** @var Column $columnComponent */ + foreach ($this->getColumns($component) as $columnComponent) { + if ($columnComponent->hasData('options')) { + $optionSource = $columnComponent->getData('options'); + $optionsArray = $optionSource instanceof OptionSourceInterface ? + $optionSource->toOptionArray() : $optionSource; + $options[$columnComponent->getName()] = $this->getOptionsArray($optionsArray ?: []); + } + } + + return $options; + } + + /** + * Get options from column filters. + * + * @return array + * @throws LocalizedException + */ + protected function getFilterOptions(): array { $options = []; $component = $this->filter->getComponent(); @@ -221,22 +283,25 @@ public function getOptions() if ($child instanceof Filters) { foreach ($child->getChildComponents() as $filter) { if ($filter instanceof Select) { - $options[$filter->getName()] = $this->getFilterOptions($filter); + $options[$filter->getName()] = $this->getOptionsArray($filter->getData('config/options')); } } } } + return $options; } /** * Convert document date(UTC) fields to default scope specified * - * @param \Magento\Framework\Api\Search\DocumentInterface $document + * @param DocumentInterface $document * @param string $componentName + * * @return void + * @throws Exception */ - public function convertDate($document, $componentName) + public function convertDate($document, $componentName): void { if (!isset($this->data[$componentName])) { return; @@ -247,7 +312,7 @@ public function convertDate($document, $componentName) continue; } $convertedDate = $this->localeDate->date( - new \DateTime($fieldValue, new \DateTimeZone('UTC')), + new DateTime($fieldValue, new DateTimeZone('UTC')), $this->locale, true ); diff --git a/app/code/Magento/Ui/Model/Manager.php b/app/code/Magento/Ui/Model/Manager.php index e3c56418c8425..1bacdc80a5c5e 100644 --- a/app/code/Magento/Ui/Model/Manager.php +++ b/app/code/Magento/Ui/Model/Manager.php @@ -7,9 +7,11 @@ namespace Magento\Ui\Model; use ArrayObject; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\CacheInterface; use Magento\Framework\Data\Argument\InterpreterInterface; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Config\CacheInterface; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\View\Element\UiComponent\ArrayObjectFactory; use Magento\Framework\View\Element\UiComponent\Config\Converter; use Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface; @@ -18,11 +20,10 @@ use Magento\Framework\View\Element\UiComponent\Config\Provider\Component\Definition as ComponentDefinition; use Magento\Framework\View\Element\UiComponent\Config\ReaderFactory; use Magento\Framework\View\Element\UiComponent\Config\UiReaderInterface; -use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\App\ObjectManager; /** - * Class Manager + * @inheritdoc + * * @deprecated 100.2.0 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -313,6 +314,7 @@ protected function createDataForComponent($name, array $componentsPool) // Create inner components foreach ($component as $subComponentName => $subComponent) { if (is_array($subComponent)) { + // phpcs:ignore Magento2.Performance.ForeachArrayMerge $resultConfiguration[ManagerInterface::CHILDREN_KEY] = array_merge( $resultConfiguration[ManagerInterface::CHILDREN_KEY], $this->createDataForComponent($subComponentName, $subComponent) @@ -386,8 +388,7 @@ protected function mergeAttributes(array $componentData, array $rootComponentDat */ protected function createName(array $componentData, $key, $componentName) { - return isset($componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY]) - ? $componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY] - : sprintf(ManagerInterface::ANONYMOUS_TEMPLATE, $componentName, $key); + return $componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY] + ?? sprintf(ManagerInterface::ANONYMOUS_TEMPLATE, $componentName, $key); } } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php index d16b1eaad7f37..d15f94bd6f2dd 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -5,17 +5,17 @@ */ namespace Magento\Ui\TemplateEngine\Xhtml; -use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\State; use Magento\Framework\Serialize\Serializer\JsonHexTag; -use Magento\Framework\View\Layout\Generator\Structure; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Framework\View\TemplateEngine\Xhtml\Template; -use Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface; +use Magento\Framework\View\Layout\Generator\Structure; use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Template; use Psr\Log\LoggerInterface; /** - * Class Result + * Convert DOMElement to string representation */ class Result implements ResultInterface { @@ -49,6 +49,11 @@ class Result implements ResultInterface */ private $jsonSerializer; + /** + * @var State + */ + private $state; + /** * @param Template $template * @param CompilerInterface $compiler @@ -56,6 +61,7 @@ class Result implements ResultInterface * @param Structure $structure * @param LoggerInterface $logger * @param JsonHexTag $jsonSerializer + * @param State $state */ public function __construct( Template $template, @@ -63,14 +69,16 @@ public function __construct( UiComponentInterface $component, Structure $structure, LoggerInterface $logger, - JsonHexTag $jsonSerializer = null + JsonHexTag $jsonSerializer, + State $state ) { $this->template = $template; $this->compiler = $compiler; $this->component = $component; $this->structure = $structure; $this->logger = $logger; - $this->jsonSerializer = $jsonSerializer ?? ObjectManager::getInstance()->get(JsonHexTag::class); + $this->jsonSerializer = $jsonSerializer; + $this->state = $state; } /** @@ -116,8 +124,11 @@ public function __toString() $this->appendLayoutConfiguration(); $result = $this->compiler->postprocessing($this->template->__toString()); } catch (\Throwable $e) { - $this->logger->critical($e->getMessage()); + $this->logger->critical($e); $result = $e->getMessage(); + if ($this->state->getMode() === State::MODE_DEVELOPER) { + $result .= "<pre><code>Exception in {$e->getFile()}:{$e->getLine()}</code></pre>"; + } } return $result; } diff --git a/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterSearchResultsBySelectActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterSearchResultsBySelectActionGroup.xml new file mode 100644 index 0000000000000..5ae764ce100aa --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterSearchResultsBySelectActionGroup.xml @@ -0,0 +1,26 @@ +<?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="AdminGridFilterSearchResultsBySelectActionGroup"> + <annotations> + <description>Filters an Admin Grid page using the provided Filter Selector and Search Value.</description> + </annotations> + <arguments> + <argument name="attributeSelector" type="string" defaultValue="store_id"/> + <argument name="attributeValue" type="string" defaultValue="{{_defaultStore.name}}"/> + </arguments> + + <conditionalClick selector="{{AdminGridFilterControls.clearAll}}" dependentSelector="{{AdminGridFilterControls.clearAll}}" visible="true" stepKey="clearTheFiltersIfPresent"/> + <waitForPageLoad time="30" stepKey="waitForFilterApplied"/> + <click selector="{{AdminGridFilterControls.filters}}" stepKey="clickOnFilters"/> + <selectOption selector="{{AdminDataGridFilterSection.filterSelectFieldByName(attributeSelector)}}" userInput="{{attributeValue}}" stepKey="setAttributeValue"/> + <click selector="{{AdminGridFilterControls.applyFilters}}" stepKey="clickOnApplyFilters"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml index ad8182c62ae68..e93df2d26ffc4 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml @@ -13,6 +13,7 @@ <element name="filterExpand" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//button[@data-action='grid-filter-expand']" /> <element name="inputFieldByNameAttr" type="input" selector="//*[@data-part='filter-form']//input[@name='{{inputNameAttr}}']" parameterized="true" /> <element name="inputFieldByNameAttrInGrid" type="input" selector="//*[@data-role='filter-form']//input[@name='{{inputNameAttr}}']" parameterized="true"/> + <element name="filterSelectFieldByName" type="select" selector="//*[@data-part='filter-form']//select[@name='{{fieldName}}']" parameterized="true"/> <element name="apply" type="button" selector="//*[@data-part='filter-form']//button[@data-action='grid-filter-apply']" /> <element name="clear" type="button" selector=".admin__data-grid-header [data-action='grid-filter-reset']" /> </section> diff --git a/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml index 674d1d2216793..3cc120ad98176 100644 --- a/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml +++ b/app/code/Magento/Ui/Test/Mftf/Test/AdminGridFilterDeleteAndVerifyErrorMessageTest.xml @@ -47,7 +47,7 @@ <magentoCLI command="config:set system/backup/functionality_enabled 0" stepKey="setEnableBackupToNo"/> <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter created simple product in grid and add category and website created in create data--> diff --git a/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php b/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php index bee5cec1f0630..665e2e636cf91 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Test\Unit\Component\MassAction; use Magento\Framework\Api\Filter as ApiFilter; @@ -10,68 +11,77 @@ use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb as ResourceAbstractDb; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Element\UiComponentInterface; use Magento\Ui\Component\MassAction\Filter; +use PHPUnit\Framework\MockObject\MockObject; /** - * Class FilterTest + * Ui component massaction filter tests * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FilterTest extends \PHPUnit\Framework\TestCase { /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $requestMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $uiComponentFactoryMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $filterBuilderMock; - /** @var \Magento\Ui\Component\MassAction\Filter */ + /** + * @var Filter + */ private $filter; /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var ObjectManager */ private $objectManager; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $dataProviderMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $abstractDbMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $searchResultMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $uiComponentMock; /** - * \PHPUnit_Framework_MockObject_MockObject + * MockObject */ private $contextMock; + /** + * @var MockObject + */ + private $resourceAbstractDbMock; + /** * Set up */ @@ -86,7 +96,11 @@ protected function setUp() $this->requestMock = $this->createMock(RequestInterface::class); $this->dataProviderMock = $this->createMock(DataProviderInterface::class); $this->uiComponentMock = $this->createMock(UiComponentInterface::class); - $this->abstractDbMock = $this->createMock(AbstractDb::class); + $this->abstractDbMock = $this->createPartialMock( + AbstractDb::class, + ['getResource', 'addFieldToFilter'] + ); + $this->resourceAbstractDbMock = $this->createMock(ResourceAbstractDb::class); $this->contextMock = $this->createMock(ContextInterface::class); $this->searchResultMock = $this->createMock(SearchResultInterface::class); $uiComponentMockTwo = $this->createMock(UiComponentInterface::class); @@ -119,6 +133,7 @@ protected function setUp() * @param int[]|bool $excludedIds * @param int $filterExpected * @param string $conditionExpected + * @throws \Magento\Framework\Exception\LocalizedException * @dataProvider applySelectionOnTargetProviderDataProvider */ public function testApplySelectionOnTargetProvider($selectedIds, $excludedIds, $filterExpected, $conditionExpected) @@ -133,10 +148,10 @@ public function testApplySelectionOnTargetProvider($selectedIds, $excludedIds, $ public function applySelectionOnTargetProviderDataProvider() { return [ - [[1, 2, 3], 'false' , 0, 'in'], - [[1, 2, 3], [1, 2, 3] , 1, 'nin'], - ['false', [1, 2, 3] , 1, 'nin'], - ['false', 'false' , 0, ''] + [[1, 2, 3], 'false', 0, 'in'], + [[1, 2, 3], [1, 2, 3], 1, 'nin'], + ['false', [1, 2, 3], 1, 'nin'], + ['false', 'false', 0, ''] ]; } @@ -190,6 +205,7 @@ public function testApplySelectionOnTargetProviderException() * @param int[]|bool $excludedIds * @param int $filterExpected * @param string $conditionExpected + * @throws \Magento\Framework\Exception\LocalizedException * @dataProvider applySelectionOnTargetProviderDataProvider */ public function testGetCollection($selectedIds, $excludedIds, $filterExpected, $conditionExpected) @@ -207,6 +223,12 @@ public function testGetCollection($selectedIds, $excludedIds, $filterExpected, $ ->method('getParam') ->with(Filter::EXCLUDED_PARAM) ->willReturn($excludedIds); + $this->abstractDbMock->expects($this->once()) + ->method('getResource') + ->willReturn($this->resourceAbstractDbMock); + $this->abstractDbMock->expects($this->once()) + ->method('addFieldToFilter') + ->willReturnSelf(); $this->assertEquals($this->abstractDbMock, $this->filter->getCollection($this->abstractDbMock)); } @@ -217,6 +239,7 @@ public function testGetCollection($selectedIds, $excludedIds, $filterExpected, $ * @param int[]|bool $excludedIds * @param int $filterExpected * @param string $conditionExpected + * @throws \Magento\Framework\Exception\LocalizedException * @dataProvider applySelectionOnTargetProviderDataProvider */ public function testGetCollectionWithCollection($selectedIds, $excludedIds, $filterExpected, $conditionExpected) @@ -233,11 +256,20 @@ public function testGetCollectionWithCollection($selectedIds, $excludedIds, $fil $this->requestMock->expects($this->any()) ->method('getParam') - ->willReturnMap([ - ['namespace', null, ''], - [Filter::SELECTED_PARAM, null, $selectedIds], - [Filter::EXCLUDED_PARAM, null, $excludedIds], - ]); + ->willReturnMap( + [ + ['namespace', null, ''], + [Filter::SELECTED_PARAM, null, $selectedIds], + [Filter::EXCLUDED_PARAM, null, $excludedIds], + ] + ); + + $this->abstractDbMock->expects($this->once()) + ->method('getResource') + ->willReturn($this->resourceAbstractDbMock); + $this->abstractDbMock->expects($this->once()) + ->method('addFieldToFilter') + ->willReturnSelf(); $this->assertEquals($this->abstractDbMock, $this->filter->getCollection($this->abstractDbMock)); } diff --git a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php index 50bce70e08feb..1b86bc14c7df7 100755 --- a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php @@ -3,22 +3,30 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Ui\Test\Unit\Model\Export; +use Magento\Framework\Api\AttributeInterface; use Magento\Framework\Api\Search\DocumentInterface; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\DataObject; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\Component\Filters; +use Magento\Ui\Component\Filters\Type\Select; use Magento\Ui\Component\Listing\Columns; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Ui\Component\MassAction\Filter; use Magento\Ui\Model\Export\MetadataProvider; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\TestCase; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class MetadataProviderTest extends \PHPUnit\Framework\TestCase +class MetadataProviderTest extends TestCase { /** * @var MetadataProvider @@ -45,25 +53,25 @@ class MetadataProviderTest extends \PHPUnit\Framework\TestCase */ protected function setUp() { - $this->filter = $this->getMockBuilder(\Magento\Ui\Component\MassAction\Filter::class) - ->disableOriginalConstructor() - ->getMock(); + $this->filter = $this->getMockBuilder(Filter::class) + ->disableOriginalConstructor() + ->getMock(); - $this->localeDate = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class) - ->disableOriginalConstructor() - ->getMock(); + $this->localeDate = $this->getMockBuilder(TimezoneInterface::class) + ->disableOriginalConstructor() + ->getMock(); - $this->localeResolver = $this->getMockBuilder(\Magento\Framework\Locale\ResolverInterface::class) - ->disableOriginalConstructor() - ->getMock(); + $this->localeResolver = $this->getMockBuilder(ResolverInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->localeResolver->expects($this->any()) - ->method('getLocale') - ->willReturn(null); + ->method('getLocale') + ->willReturn(null); $objectManager = new ObjectManager($this); $this->model = $objectManager->getObject( - \Magento\Ui\Model\Export\MetadataProvider::class, + MetadataProvider::class, [ 'filter' => $this->filter, 'localeDate' => $this->localeDate, @@ -76,8 +84,10 @@ protected function setUp() /** * @param array $columnLabels * @param array $expected + * * @return void * @dataProvider getColumnsDataProvider + * @throws \Exception */ public function testGetHeaders(array $columnLabels, array $expected): void { @@ -97,12 +107,12 @@ public function testGetHeaders(array $columnLabels, array $expected): void public function getColumnsDataProvider(): array { return [ - [['ID'],['ID']], - [['Name'],['Name']], - [['Id'],['Id']], - [['id'],['id']], - [['IDTEST'],['IDTEST']], - [['ID TEST'],['ID TEST']], + [['ID'], ['ID']], + [['Name'], ['Name']], + [['Id'], ['Id']], + [['id'], ['id']], + [['IDTEST'], ['IDTEST']], + [['ID TEST'], ['ID TEST']], ]; } @@ -126,6 +136,7 @@ public function testGetFields() * @param string $columnLabel * @param string $columnActionsName * @param string $columnActionsLabel + * * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject */ protected function prepareColumns( @@ -136,57 +147,57 @@ protected function prepareColumns( $columnActionsLabel = 'actions_label' ) { /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $component */ - $component = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + $component = $this->getMockBuilder(UiComponentInterface::class) + ->getMockForAbstractClass(); /** @var Columns|\PHPUnit_Framework_MockObject_MockObject $columns */ - $columns = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns::class) - ->disableOriginalConstructor() - ->getMock(); + $columns = $this->getMockBuilder(Columns::class) + ->disableOriginalConstructor() + ->getMock(); /** @var Column|\PHPUnit_Framework_MockObject_MockObject $column */ - $column = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) - ->disableOriginalConstructor() - ->getMock(); + $column = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); /** @var Column|\PHPUnit_Framework_MockObject_MockObject $columnActions */ - $columnActions = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) - ->disableOriginalConstructor() - ->getMock(); + $columnActions = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); $component->expects($this->any()) - ->method('getName') - ->willReturn($componentName); - $component->expects($this->once()) - ->method('getChildComponents') - ->willReturn([$columns]); + ->method('getName') + ->willReturn($componentName); + $component->expects($this->atLeastOnce()) + ->method('getChildComponents') + ->willReturn([$columns]); - $columns->expects($this->once()) - ->method('getChildComponents') - ->willReturn([$column, $columnActions]); + $columns->expects($this->atLeastOnce()) + ->method('getChildComponents') + ->willReturn([$column, $columnActions]); $column->expects($this->any()) - ->method('getName') - ->willReturn($columnName); + ->method('getName') + ->willReturn($columnName); $column->expects($this->any()) - ->method('getData') - ->willReturnMap( - [ - ['config/label', null, $columnLabel], - ['config/dataType', null, 'data_type'], - ] - ); + ->method('getData') + ->willReturnMap( + [ + ['config/label', null, $columnLabel], + ['config/dataType', null, 'data_type'], + ] + ); $columnActions->expects($this->any()) - ->method('getName') - ->willReturn($columnActionsName); + ->method('getName') + ->willReturn($columnActionsName); $columnActions->expects($this->any()) - ->method('getData') - ->willReturnMap( - [ - ['config/label', null, $columnActionsLabel], - ['config/dataType', null, 'actions'], - ] - ); + ->method('getData') + ->willReturnMap( + [ + ['config/label', null, $columnActionsLabel], + ['config/dataType', null, 'actions'], + ] + ); return $component; } @@ -196,25 +207,26 @@ protected function prepareColumns( * @param array $fields * @param array $options * @param array $expected + * * @dataProvider getRowDataProvider */ public function testGetRowData($key, $fields, $options, $expected) { /** @var DocumentInterface|\PHPUnit_Framework_MockObject_MockObject $document */ - $document = $this->getMockBuilder(\Magento\Framework\Api\Search\DocumentInterface::class) - ->getMockForAbstractClass(); + $document = $this->getMockBuilder(DocumentInterface::class) + ->getMockForAbstractClass(); - $attribute = $this->getMockBuilder(\Magento\Framework\Api\AttributeInterface::class) - ->getMockForAbstractClass(); + $attribute = $this->getMockBuilder(AttributeInterface::class) + ->getMockForAbstractClass(); $document->expects($this->once()) - ->method('getCustomAttribute') - ->with($fields[0]) - ->willReturn($attribute); + ->method('getCustomAttribute') + ->with($fields[0]) + ->willReturn($attribute); $attribute->expects($this->once()) - ->method('getValue') - ->willReturn($key); + ->method('getValue') + ->willReturn($key); $result = $this->model->getRowData($document, $fields, $options); $this->assertTrue(is_array($result)); @@ -249,7 +261,7 @@ public function getRowDataProvider() ], ], 'expected' => [ - '', + 'key_2', ], ], [ @@ -265,54 +277,131 @@ public function getRowDataProvider() /** * @param string $filter - * @param array $options + * @param array $filterOptions + * @param array $columnsOptions * @param array $expected + * + * @throws LocalizedException * @dataProvider getOptionsDataProvider */ - public function testGetOptions($filter, $options, $expected) + public function testGetOptions(string $filter, array $filterOptions, array $columnsOptions, array $expected) { - $component = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + $component = $this->prepareColumnsWithOptions($filter, $filterOptions, $columnsOptions); - $childComponent = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + $this->filter->expects($this->exactly(2)) + ->method('getComponent') + ->willReturn($component); - $filters = $this->getMockBuilder(\Magento\Ui\Component\Filters::class) - ->disableOriginalConstructor() - ->getMock(); + $result = $this->model->getOptions(); + $this->assertTrue(is_array($result)); + $this->assertCount(2, $result); + $this->assertEquals($expected, $result); + } - $select = $this->getMockBuilder(\Magento\Ui\Component\Filters\Type\Select::class) - ->disableOriginalConstructor() - ->getMock(); + /** + * @param string $filter + * @param array $filterOptions + * + * @param array $columnsOptions + * + * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected function prepareColumnsWithOptions(string $filter, array $filterOptions, array $columnsOptions) + { + /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $component */ + $component = $this->getMockBuilder(UiComponentInterface::class) + ->getMockForAbstractClass(); + + $listingTopComponent = $this->getMockBuilder(UiComponentInterface::class) + ->getMockForAbstractClass(); + + $filters = $this->getMockBuilder(Filters::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var Columns|\PHPUnit_Framework_MockObject_MockObject $columns */ + $columns = $this->getMockBuilder(Columns::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $column */ + $column = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $columnActions */ + $columnActions = $this->getMockBuilder(Column::class) + ->disableOriginalConstructor() + ->getMock(); - $this->filter->expects($this->once()) - ->method('getComponent') - ->willReturn($component); + $component->expects($this->any()) + ->method('getName') + ->willReturn('columns_component_name'); + $component->expects($this->atLeastOnce()) + ->method('getChildComponents') + ->willReturn(['columns' => $columns, 'listing_top' => $listingTopComponent]); - $component->expects($this->once()) - ->method('getChildComponents') - ->willReturn(['listing_top' => $childComponent]); + $listingTopComponent->expects($this->once()) + ->method('getChildComponents') + ->willReturn([$filters]); - $childComponent->expects($this->once()) - ->method('getChildComponents') - ->willReturn([$filters]); + $select = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); $filters->expects($this->once()) - ->method('getChildComponents') - ->willReturn([$select]); + ->method('getChildComponents') + ->willReturn([$select]); $select->expects($this->any()) - ->method('getName') - ->willReturn($filter); + ->method('getName') + ->willReturn($filter); $select->expects($this->any()) - ->method('getData') - ->with('config/options') - ->willReturn($options); + ->method('getData') + ->with('config/options') + ->willReturn($filterOptions); - $result = $this->model->getOptions(); - $this->assertTrue(is_array($result)); - $this->assertCount(1, $result); - $this->assertEquals($expected, $result); + $columns->expects($this->atLeastOnce()) + ->method('getChildComponents') + ->willReturn([$column, $columnActions]); + + $column->expects($this->any()) + ->method('getName') + ->willReturn('column_name'); + + $optionSource = $this->getMockBuilder(OptionSourceInterface::class) + ->getMockForAbstractClass(); + $optionSource->expects($this->once()) + ->method('toOptionArray') + ->willReturn($columnsOptions); + + $column->expects($this->any()) + ->method('getData') + ->willReturnMap( + [ + ['config/label', null, 'column_label'], + ['config/dataType', null, 'data_type'], + ['options', null, $optionSource], + ] + ); + + $column->expects($this->once()) + ->method('hasData') + ->willReturn(true) + ->with('options'); + + $columnActions->expects($this->any()) + ->method('getName') + ->willReturn('column_actions_name'); + $columnActions->expects($this->any()) + ->method('getData') + ->willReturnMap( + [ + ['config/label', null, 'column_actions_label'], + ['config/dataType', null, 'actions'], + ] + ); + + return $component; } /** @@ -323,7 +412,13 @@ public function getOptionsDataProvider() return [ [ 'filter' => 'filter_name', - 'options' => [ + 'filterOptions' => [ + [ + 'value' => 'value_1', + 'label' => 'label_1', + ] + ], + 'columnsOptions' => [ [ 'value' => 'value_1', 'label' => 'label_1', @@ -333,11 +428,25 @@ public function getOptionsDataProvider() 'filter_name' => [ 'value_1' => 'label_1', ], + 'column_name' => [ + 'value_1' => 'label_1', + ] ], ], [ 'filter' => 'filter_name', - 'options' => [ + 'filterOptions' => [ + [ + 'value' => [ + [ + 'value' => 'value_2', + 'label' => 'label_2', + ], + ], + 'label' => 'label_1', + ] + ], + 'columnsOptions' => [ [ 'value' => [ [ @@ -352,11 +461,14 @@ public function getOptionsDataProvider() 'filter_name' => [ 'value_2' => 'label_1label_2', ], + 'column_name' => [ + 'value_2' => 'label_1label_2', + ] ], ], [ 'filter' => 'filter_name', - 'options' => [ + 'filterOptions' => [ [ 'value' => [ [ @@ -372,10 +484,12 @@ public function getOptionsDataProvider() 'label' => 'label_1', ] ], + 'columnsOptions' => [], 'expected' => [ 'filter_name' => [ 'value_3' => 'label_1label_2label_3', ], + 'column_name' => [] ], ], ]; @@ -386,29 +500,31 @@ public function getOptionsDataProvider() * * @param string $fieldValue * @param string $expected + * * @dataProvider convertDateProvider * @covers \Magento\Ui\Model\Export\MetadataProvider::convertDate() + * @throws \Exception */ public function testConvertDate($fieldValue, $expected) { $componentName = 'component_name'; /** @var DocumentInterface|\PHPUnit_Framework_MockObject_MockObject $document */ - $document = $this->getMockBuilder(\Magento\Framework\DataObject::class) - ->disableOriginalConstructor() - ->getMock(); + $document = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); $document->expects($this->once()) - ->method('getData') - ->with('field') - ->willReturn($fieldValue); + ->method('getData') + ->with('field') + ->willReturn($fieldValue); $this->localeDate->expects($this->once()) - ->method('date') - ->willReturn(new \DateTime($fieldValue, new \DateTimeZone('UTC'))); + ->method('date') + ->willReturn(new \DateTime($fieldValue, new \DateTimeZone('UTC'))); $document->expects($this->once()) - ->method('setData') - ->with('field', $expected); + ->method('setData') + ->with('field', $expected); $this->model->convertDate($document, $componentName); } diff --git a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php new file mode 100644 index 0000000000000..0890a3c095c40 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -0,0 +1,144 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Ui\Test\Unit\TemplateEngine\Xhtml; + +use Magento\Framework\App\State; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Template; +use Magento\Ui\Component\Listing; +use Magento\Ui\TemplateEngine\Xhtml\Result; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Test for \Magento\Ui\TemplateEngine\Xhtml\Result. + */ +class ResultTest extends TestCase +{ + /** + * Stub simple html element + */ + private const STUB_HTML_ELEMENT = '<div id="id"></div>'; + + /** + * @var Result + */ + private $model; + + /** + * @var ObjectManagerHelper|MockObject + */ + private $objectManagerHelper; + + /** + * @var Template|MockObject + */ + private $templateMock; + + /** + * @var CompilerInterface|MockObject + */ + private $compilerMock; + + /** + * @var UiComponentInterface|MockObject + */ + private $componentMock; + + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var State|MockObject + */ + private $stateMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->templateMock = $this->createMock(Template::class); + $this->compilerMock = $this->createMock(CompilerInterface::class); + $this->componentMock = $this->createMock(Listing::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->stateMock = $this->createMock(State::class); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + Result::class, + [ + 'template' => $this->templateMock, + 'compiler' => $this->compilerMock, + 'component' => $this->componentMock, + 'logger' => $this->loggerMock, + 'state' => $this->stateMock, + ] + ); + } + + /** + * To string method with exception message + * + * @return void + */ + public function testToStringWithException(): void + { + $e = new \Exception(); + + $this->templateMock->expects($this->once()) + ->method('getDocumentElement') + ->willThrowException($e); + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($e); + $this->assertEquals( + '<pre><code>Exception in ' . $e->getFile() . ':' . $e->getLine() . '</code></pre>', + $this->model->__toString() + ); + } + + /** + * To string method + * + * @return void + */ + public function testToString(): void + { + $domElementMock = $this->getMockBuilder(\DOMElement::class) + ->setConstructorArgs(['arg']) + ->getMock(); + + $this->templateMock->expects($this->once()) + ->method('getDocumentElement') + ->willReturn($domElementMock); + $this->compilerMock->expects($this->once()) + ->method('compile') + ->with( + $this->isInstanceOf(\DOMElement::class), + $this->componentMock, + $this->componentMock + ); + $this->templateMock->expects($this->once())->method('__toString'); + $this->compilerMock->expects($this->once()) + ->method('postprocessing') + ->willReturn(self::STUB_HTML_ELEMENT); + + $this->assertEquals(self::STUB_HTML_ELEMENT, $this->model->__toString()); + } +} diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js index 2549fa93a834f..0464788d155e2 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/image-preview.js @@ -239,7 +239,7 @@ define([ handleKeyDown: function (e) { var key = keyCodes[e.keyCode]; - if (this.visibleRecord() !== null) { + if (this.visibleRecord() !== null && document.activeElement.tagName !== 'INPUT') { if (key === 'pageLeftKey') { this.prev(this.displayedRecord()); } else if (key === 'pageRightKey') { diff --git a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js index 547cdab16cdf1..aa9989251b656 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/data-storage.js @@ -188,7 +188,8 @@ define([ result = { items: this.getByIds(request.ids), - totalRecords: request.totalRecords + totalRecords: request.totalRecords, + errorMessage: request.errorMessage }; delay ? @@ -216,7 +217,8 @@ define([ this._requests.push({ ids: this.getIds(data.items), params: params, - totalRecords: data.totalRecords + totalRecords: data.totalRecords, + errorMessage: data.errorMessage }); return this; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js index 6ff7c1f673213..ab806e89385b6 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/optgroup.js @@ -250,7 +250,7 @@ define([ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document. // That's why we first added them without selection. Now it's time to set the selection. - if (previousSelectedValues.length) { + if (previousSelectedValues.length && newOptions.value) { isSelected = ko.utils.arrayIndexOf( previousSelectedValues, ko.selectExtensions.readValue(newOptions.value) diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html b/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html index 089ee21bec15c..788cb0c2b5e56 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/masonry.html @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ --> -<div data-role="grid-wrapper" class="masonry-image-grid" attr="'data-id': containerId"> +<div data-role="grid-wrapper" class="masonry-image-grid" attr="'data-id': containerId" tabindex="0"> <div class="masonry-image-column" repeat="foreach: rows, item: '$row'"> <div outerfasteach="data: getVisible(), as: '$col'" template="getBody()"/> </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html index 5e7fd11dbf693..7d7d4b6ae88cb 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html @@ -27,7 +27,7 @@ <h1 id="modal-title-<%- data.id %>" class="modal-title" <% if(data.subTitle){ %> <span class="modal-subtitle" - data-role="subtitle"> + data-role="subTitle"> <%= data.subTitle %> </span> <% } %> diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html index 53661ed8df87f..08376964eee63 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html @@ -27,7 +27,7 @@ <h1 id="modal-title-<%- data.id %>" class="modal-title" <% if(data.subTitle){ %> <span class="modal-subtitle" - data-role="subtitle"> + data-role="subTitle"> <%= data.subTitle %> </span> <% } %> diff --git a/app/code/Magento/Ui/view/frontend/web/js/model/messages.js b/app/code/Magento/Ui/view/frontend/web/js/model/messages.js index fb9a20c054da2..f0680fe6eaae5 100644 --- a/app/code/Magento/Ui/view/frontend/web/js/model/messages.js +++ b/app/code/Magento/Ui/view/frontend/web/js/model/messages.js @@ -48,6 +48,10 @@ define([ message = messageObj.message.replace(expr, function (varName) { varName = varName.substr(1); + if (!isNaN(varName)) { + varName--; + } + if (messageObj.parameters.hasOwnProperty(varName)) { return messageObj.parameters[varName]; } diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 64da25a2a170b..5b333e2dc2d5c 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -856,7 +856,7 @@ private function mapCurrencyCode($code) 'CNH' => 'CNY' ]; - return isset($currencyMapping[$code]) ? $currencyMapping[$code] : $code; + return $currencyMapping[$code] ?? $code; } /** diff --git a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml index 9caa32609c487..bd278c9dbe975 100644 --- a/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml +++ b/app/code/Magento/Ups/Test/Mftf/Test/DefaultConfigForUPSTypeTest.xml @@ -26,7 +26,7 @@ <!--Collapse UPS tab and logout--> <comment userInput="Collapse UPS tab and logout" stepKey="collapseTabAndLogout"/> <click selector="{{AdminShippingMethodsUpsSection.carriersUpsTab}}" stepKey="collapseTab"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Set shipping methods UPS type to default --> <comment userInput="Set shipping methods UPS type to default" stepKey="setToDefaultShippingMethodsUpsType"/> diff --git a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php index 34dd4f0fe142b..e0580629dd638 100644 --- a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php @@ -196,7 +196,7 @@ public function scopeConfigGetValue(string $path) 'carriers/ups/access_license_number' => 'acn', ]; - return isset($pathMap[$path]) ? $pathMap[$path] : null; + return $pathMap[$path] ?? null; } /** diff --git a/app/code/Magento/UrlRewrite/Block/Edit/Form.php b/app/code/Magento/UrlRewrite/Block/Edit/Form.php index 65312c9cc01b8..2bc92ecf78ae1 100644 --- a/app/code/Magento/UrlRewrite/Block/Edit/Form.php +++ b/app/code/Magento/UrlRewrite/Block/Edit/Form.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\UrlRewrite\Block\Edit; /** @@ -95,6 +97,7 @@ protected function _construct() /** * Initialize form values + * * Set form data either from model values or from session * * @return $this @@ -194,7 +197,7 @@ protected function _prepareForm() 'label' => __('Redirect Type'), 'title' => __('Redirect Type'), 'name' => 'redirect_type', - 'options' => $this->optionProvider->toOptionArray(), + 'options' => $this->optionProvider->getOptions(), 'value' => $this->_formValues['redirect_type'] ] ); diff --git a/app/code/Magento/UrlRewrite/Block/GridContainer.php b/app/code/Magento/UrlRewrite/Block/GridContainer.php index b95b724fa05cc..1a3a6e89fa854 100644 --- a/app/code/Magento/UrlRewrite/Block/GridContainer.php +++ b/app/code/Magento/UrlRewrite/Block/GridContainer.php @@ -3,10 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\UrlRewrite\Block; /** + * Url rewrite grid container class + * * @api + * @deprecated Moved to UI component implementation * @since 100.0.2 */ class GridContainer extends \Magento\Backend\Block\Widget\Grid\Container diff --git a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/InlineEdit.php b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/InlineEdit.php new file mode 100644 index 0000000000000..589127792a478 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/InlineEdit.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; + +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\Controller\Result\Json; +use Magento\Framework\Controller\Result\JsonFactory; +use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteFactory as UrlRewriteFactoryAlias; +use Magento\UrlRewrite\Model\UrlRewrite; +use Magento\UrlRewrite\Model\UrlRewriteFactory; + +/** + * Inline edit action class + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class InlineEdit extends Rewrite implements HttpPostActionInterface +{ + /** + * @var JsonFactory + */ + private $jsonFactory; + + /** + * @var UrlRewriteFactory + */ + private $urlRewriteFactory; + + /** + * @var UrlRewriteFactoryAlias + */ + private $urlRewriteResourceFactory; + + /** + * @param Context $context + * @param UrlRewriteFactory $urlRewriteFactory + * @param UrlRewriteFactoryAlias $urlRewriteResourceFactory + * @param JsonFactory $jsonFactory + */ + public function __construct( + Context $context, + UrlRewriteFactory $urlRewriteFactory, + UrlRewriteFactoryAlias $urlRewriteResourceFactory, + JsonFactory $jsonFactory + ) { + parent::__construct($context); + $this->urlRewriteFactory = $urlRewriteFactory; + $this->urlRewriteResourceFactory = $urlRewriteResourceFactory; + $this->jsonFactory = $jsonFactory; + } + + /** + * Inline edit save action + * + * @return Json + */ + public function execute(): Json + { + $resultJson = $this->jsonFactory->create(); + $error = false; + $messages = []; + + $postItems = $this->getRequest()->getParam( + 'items', + [] + ); + if (!($this->getRequest()->getParam('isAjax') && count($postItems))) { + return $resultJson->setData( + [ + 'messages' => [__('Please correct the data sent.')], + 'error' => true, + ] + ); + } + + $urlRewriteResource = $this->urlRewriteResourceFactory->create(); + foreach (array_keys($postItems) as $urlRewriteId) { + $urlRewrite = $this->urlRewriteFactory->create(); + $urlRewriteResource->load($urlRewrite, $urlRewriteId); + + try { + $urlRewrite->addData($postItems[$urlRewriteId]); + $urlRewriteResource->save($urlRewrite); + } catch (\RuntimeException $e) { + $messages[] = $this->getErrorWithUrlRewriteId( + $urlRewrite, + $e->getMessage() + ); + $error = true; + } catch (\Exception $e) { + $messages[] = $this->getErrorWithUrlRewriteId( + $urlRewrite, + __('Something went wrong while saving the url rewrite.') + ); + $error = true; + } + } + + return $resultJson->setData( + [ + 'messages' => $messages, + 'error' => $error + ] + ); + } + + /** + * Get error message for url rewrite + * + * @param UrlRewrite $urlRewrite + * @param string $errorText + * @return string + */ + private function getErrorWithUrlRewriteId(UrlRewrite $urlRewrite, $errorText): string + { + return '[Url rewrite ID: ' . $urlRewrite->getId() . '] ' . $errorText; + } +} diff --git a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/MassDelete.php b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/MassDelete.php new file mode 100644 index 0000000000000..51f7ddc4b53f9 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/MassDelete.php @@ -0,0 +1,85 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; + +use Exception; +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\Controller\Result\Redirect; +use Magento\Framework\Exception\LocalizedException; +use Magento\Ui\Component\MassAction\Filter; +use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory as CollectionFactory; + +/** + * Mass delete action class + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MassDelete extends Rewrite implements HttpPostActionInterface +{ + /** + * @var Filter + */ + private $filter; + + /** + * @var CollectionFactory + */ + private $collectionFactory; + + /** + * @param Context $context + * @param Filter $filter + * @param CollectionFactory $collectionFactory + */ + public function __construct( + Context $context, + Filter $filter, + CollectionFactory $collectionFactory + ) { + $this->filter = $filter; + $this->collectionFactory = $collectionFactory; + parent::__construct($context); + } + + /** + * Mass delete action + * + * @return Redirect + * @throws LocalizedException + */ + public function execute(): Redirect + { + $collection = $this->filter->getCollection($this->collectionFactory->create()); + + $notProcessedCount = $processedCount = 0; + try { + foreach ($collection as $urlRewrite) { + $urlRewrite->delete(); + $processedCount++; + } + } catch (Exception $e) { + $this->getMessageManager()->addExceptionMessage($e); + $notProcessedCount++; + } + + $this->getMessageManager()->addSuccessMessage( + __('A total of %1 record(s) have been deleted.', $processedCount) + ); + + if ($notProcessedCount > 0) { + $this->getMessageManager()->addErrorMessage( + __('A total of %1 record(s) haven\'t been deleted.', $notProcessedCount) + ); + } + + $resultRedirect = $this->resultRedirectFactory->create(); + return $resultRedirect->setPath('*/*/'); + } +} diff --git a/app/code/Magento/UrlRewrite/Model/OptionProvider.php b/app/code/Magento/UrlRewrite/Model/OptionProvider.php index ec70dad90e7cc..ddcd436691791 100644 --- a/app/code/Magento/UrlRewrite/Model/OptionProvider.php +++ b/app/code/Magento/UrlRewrite/Model/OptionProvider.php @@ -5,14 +5,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\UrlRewrite\Model; -use Magento\Framework\Option\ArrayInterface; +use Magento\Framework\Data\OptionSourceInterface; /** - * @codeCoverageIgnore + * Redirect type OptionProvider class */ -class OptionProvider implements ArrayInterface +class OptionProvider implements OptionSourceInterface { /** * Permanent redirect code @@ -20,19 +22,38 @@ class OptionProvider implements ArrayInterface const PERMANENT = 301; /** - * Redirect code + * Temporary redirect code */ const TEMPORARY = 302; /** - * {@inheritdoc} + * Retrieve redirect type options + * + * @return array + */ + public function toOptionArray(): array + { + $options = []; + foreach ($this->getOptions() as $value => $label) { + $options[] = [ + 'label' => $label, + 'value' => $value + ]; + } + return $options; + } + + /** + * Retrieve options for edit form + * + * @return array */ - public function toOptionArray() + public function getOptions(): array { return [ 0 => __('No'), self::TEMPORARY => __('Temporary (302)'), - self::PERMANENT => __('Permanent (301)'), + self::PERMANENT => __('Permanent (301)') ]; } } diff --git a/app/code/Magento/UrlRewrite/Model/UrlRewrite.php b/app/code/Magento/UrlRewrite/Model/UrlRewrite.php index 83d9e7c5cf335..5f29008621c1a 100644 --- a/app/code/Magento/UrlRewrite/Model/UrlRewrite.php +++ b/app/code/Magento/UrlRewrite/Model/UrlRewrite.php @@ -3,12 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\UrlRewrite\Model; use Magento\Framework\App\ObjectManager; use Magento\Framework\Serialize\Serializer\Json; /** + * UrlRewrite model class + * * @method int getEntityId() * @method string getEntityType() * @method int getRedirectType() @@ -32,6 +36,7 @@ class UrlRewrite extends \Magento\Framework\Model\AbstractModel /** * UrlRewrite constructor. + * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource @@ -63,6 +68,8 @@ protected function _construct() } /** + * Get metadata + * * @return array * @api */ @@ -76,7 +83,6 @@ public function getMetadata() * Overwrite Metadata in the object. * * @param array|string $metadata - * * @return $this */ public function setMetadata($metadata) diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddCustomUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddCustomUrlRewriteActionGroup.xml index d4bcb5bbb414f..3a03b4accdfcf 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddCustomUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddCustomUrlRewriteActionGroup.xml @@ -33,6 +33,6 @@ <click selector="{{AdminUrlRewriteEditSection.redirectTypeValue('redirectTypeValue')}}" stepKey="selectRedirectTypeValue"/> <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescription"/> <click selector="{{AdminUrlRewriteEditSection.saveButton}}" stepKey="clickOnSaveButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> + <seeElement selector="{{AdminMessagesSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteActionGroup.xml index 55f18ae5a0187..8c578d4c79470 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteActionGroup.xml @@ -22,17 +22,19 @@ </arguments> <amOnPage url="{{AdminUrlRewriteEditPage.url}}" stepKey="openUrlRewriteEditPage"/> - <waitForElementVisible selector="{{AdminUrlRewriteEditSection.createCustomUrlRewrite}}" stepKey="waitForCreateUrlRewriteVisible"/> - <selectOption selector="{{AdminUrlRewriteEditSection.createCustomUrlRewrite}}" userInput="{{customUrlRewriteValue}}" stepKey="selectUrlRewriteTypeOption"/> - <waitForElementVisible selector="{{AdminUrlRewriteEditSection.categoryInTree(category)}}" stepKey="waitForCategoryInTreeVisible"/> - <click selector="{{AdminUrlRewriteEditSection.categoryInTree(category)}}" stepKey="clickOnCategoryInTree"/> - <waitForElementVisible selector="{{AdminUrlRewriteEditSection.store}}" stepKey="waitForStoreSelectVisible"/> - <selectOption selector="{{AdminUrlRewriteEditSection.store}}" userInput="{{storeValue}}" stepKey="selectStoreOption"/> - <fillField selector="{{AdminUrlRewriteEditSection.requestPath}}" userInput="{{requestPath}}" stepKey="fillRequestPathField"/> - <selectOption selector="{{AdminUrlRewriteEditSection.redirectType}}" userInput="{{redirectTypeValue}}" stepKey="selectRedirectType"/> - <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescriptionField"/> - <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSaveButton"/> - <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessage"/> - <see selector="{{AdminMessagesSection.success}}" userInput="The URL Rewrite has been saved." stepKey="seeSuccessMessage"/> + <waitForPageLoad stepKey="waitForUrlRewriteEditPageToLoad"/> + <click selector="{{AdminUrlRewriteEditSection.createCustomUrlRewrite}}" stepKey="clickOnCustonUrlRewrite"/> + <click selector="{{AdminUrlRewriteEditSection.createCustomUrlRewriteValue('customUrlRewriteValue')}}" stepKey="selectForCategory"/> + <waitForPageLoad stepKey="waitForCategoryEditSectionToLoad"/> + <click selector="{{AdminUrlRewriteEditSection.categoryInTree(category)}}" stepKey="selectCategoryInTree"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <click selector="{{AdminUrlRewriteEditSection.store}}" stepKey="clickOnStore"/> + <click selector="{{AdminUrlRewriteEditSection.storeValue('storeValue')}}" stepKey="clickOnStoreValue"/> + <fillField selector="{{AdminUrlRewriteEditSection.requestPath}}" userInput="{{requestPath}}" stepKey="fillRequestPath"/> + <click selector="{{AdminUrlRewriteEditSection.redirectType}}" stepKey="selectRedirectType"/> + <click selector="{{AdminUrlRewriteEditSection.redirectTypeValue('redirectTypeValue')}}" stepKey="clickOnRedirectTypeValue"/> + <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescription"/> + <click selector="{{AdminUrlRewriteEditSection.saveButton}}" stepKey="clickOnSaveButton"/> + <seeElement selector="{{AdminMessagesSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteForProductActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteForProductActionGroup.xml index 51436fc5de584..3a72c73f3e54a 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteForProductActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminAddUrlRewriteForProductActionGroup.xml @@ -29,6 +29,6 @@ <click selector="{{AdminUrlRewriteEditSection.redirectTypeValue('redirectTypeValue')}}" stepKey="clickOnRedirectTypeValue"/> <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescription"/> <click selector="{{AdminUrlRewriteEditSection.saveButton}}" stepKey="clickOnSaveButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> + <seeElement selector="{{AdminMessagesSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminDeleteUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminDeleteUrlRewriteActionGroup.xml index bc3953c4dedd4..a5519e84b4c03 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminDeleteUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminDeleteUrlRewriteActionGroup.xml @@ -18,18 +18,20 @@ <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteEditPage"/> <waitForPageLoad stepKey="waitForUrlRewriteEditPageToLoad"/> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{requestPath}}" stepKey="fillRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{requestPath}}" stepKey="fillRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> - <click selector="{{AdminUrlRewriteIndexSection.editButton('1')}}" stepKey="clickOnEditButton"/> + <click selector="{{AdminUrlRewriteIndexSection.rowSelectAction('1')}}" stepKey="clickOnRowSelectButton"/> + <click selector="{{AdminUrlRewriteIndexSection.rowEditAction('1')}}" stepKey="clickOnEditButton"/> <waitForPageLoad stepKey="waitForEditPageToLoad"/> <click selector="{{AdminUrlRewriteEditSection.deleteButton}}" stepKey="clickOnDeleteButton"/> <waitForPageLoad stepKey="waitForPageToLoad2"/> <waitForElementVisible selector="{{AdminUrlRewriteEditSection.okButton}}" stepKey="waitForOkButtonToVisible"/> <click selector="{{AdminUrlRewriteEditSection.okButton}}" stepKey="clickOnOkButton"/> <waitForPageLoad stepKey="waitForPageToLoad3"/> - <see selector="{{AdminUrlRewriteIndexSection.successMessage}}" userInput="You deleted the URL rewrite." stepKey="seeSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the URL rewrite." stepKey="seeSuccessMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchAndSelectUrlRewriteInGridActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchAndSelectUrlRewriteInGridActionGroup.xml index f2f114f01cc9e..6d3ddb69b2b58 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchAndSelectUrlRewriteInGridActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchAndSelectUrlRewriteInGridActionGroup.xml @@ -18,12 +18,14 @@ <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteEditPage"/> <waitForPageLoad stepKey="waitForUrlRewriteEditPageToLoad"/> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{requestPath}}" stepKey="fillRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{requestPath}}" stepKey="fillRequestPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> - <click selector="{{AdminUrlRewriteIndexSection.editButton('1')}}" stepKey="clickOnEditButton"/> + <click selector="{{AdminUrlRewriteIndexSection.rowSelectAction('1')}}" stepKey="clickOnRowSelectButton"/> + <click selector="{{AdminUrlRewriteIndexSection.rowEditAction('1')}}" stepKey="clickOnEditButton"/> <waitForPageLoad stepKey="waitForEditPageToLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchByRequestPathActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchByRequestPathActionGroup.xml index 99ac4ea160f82..7661ed8c04992 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchByRequestPathActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchByRequestPathActionGroup.xml @@ -20,13 +20,14 @@ <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteEditPage"/> <waitForPageLoad stepKey="waitForUrlRewriteEditPageToLoad"/> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{redirectPath}}" stepKey="fillRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{redirectPath}}" stepKey="fillRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> - <see selector="{{AdminUrlRewriteIndexSection.requestPathColumn('1')}}" userInput="{{redirectPath}}" stepKey="seeTheRedirectPathForOldUrl"/> - <see selector="{{AdminUrlRewriteIndexSection.targetPathColumn('1')}}" userInput="{{targetPath}}" stepKey="seeTheTargetPath"/> - <see selector="{{AdminUrlRewriteIndexSection.redirectTypeColumn('1')}}" userInput="{{redirectType}}" stepKey="seeTheRedirectTypeForOldUrl"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="{{redirectPath}}" stepKey="seeTheRedirectPathForOldUrl"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Target Path')}}" userInput="{{targetPath}}" stepKey="seeTheTargetPath"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Redirect Type')}}" userInput="{{redirectType}}" stepKey="seeTheRedirectTypeForOldUrl"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchDeletedUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchDeletedUrlRewriteActionGroup.xml index 2d7178f72f407..8f0a2c1731c3d 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchDeletedUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminSearchDeletedUrlRewriteActionGroup.xml @@ -18,11 +18,12 @@ <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="openUrlRewriteEditPage"/> <waitForPageLoad stepKey="waitForUrlRewriteEditPageToLoad"/> - <click selector="{{AdminUrlRewriteIndexSection.resetButton}}" stepKey="clickOnResetButton"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> <waitForPageLoad stepKey="waitForPageToLoad"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="{{requestPath}}" stepKey="fillRedirectPathFilter"/> - <click selector="{{AdminUrlRewriteIndexSection.searchButton}}" stepKey="clickOnSearchButton"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{requestPath}}" stepKey="fillRedirectPathFilter"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> - <see selector="{{AdminUrlRewriteIndexSection.emptyRecords}}" userInput="We couldn't find any records." stepKey="seeEmptyRecordMessage"/> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="seeEmptyRecordMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateCustomUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateCustomUrlRewriteActionGroup.xml index 0d0c754fe076e..69b5906c9f6e1 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateCustomUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateCustomUrlRewriteActionGroup.xml @@ -27,6 +27,6 @@ <selectOption selector="{{AdminUrlRewriteEditSection.redirectType}}" userInput="{{redirectTypeValue}}" stepKey="selectRedirectTypeValue"/> <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescription"/> <click selector="{{AdminUrlRewriteEditSection.saveButton}}" stepKey="clickOnSaveButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> + <seeElement selector="{{AdminMessagesSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateUrlRewriteActionGroup.xml b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateUrlRewriteActionGroup.xml index 4b884448a7653..386836fe2da69 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateUrlRewriteActionGroup.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/ActionGroup/AdminUpdateUrlRewriteActionGroup.xml @@ -26,6 +26,6 @@ <click selector="{{AdminUrlRewriteEditSection.redirectTypeValue(redirectTypeValue)}}" stepKey="selectRedirectTypeValue"/> <fillField selector="{{AdminUrlRewriteEditSection.description}}" userInput="{{description}}" stepKey="fillDescription"/> <click selector="{{AdminUrlRewriteEditSection.saveButton}}" stepKey="clickOnSaveButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> + <seeElement selector="{{AdminMessagesSection.successMessage}}" stepKey="seeSuccessSaveMessage"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml index 7b789845fe249..b6a155c9db6fb 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Section/AdminUrlRewriteIndexSection.xml @@ -9,18 +9,11 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminUrlRewriteIndexSection"> - <element name="requestPathFilter" type="input" selector="#urlrewriteGrid_filter_request_path"/> - <element name="requestPathColumnValue" type="text" selector="//*[@id='urlrewriteGrid']//tbody//td[@data-column='request_path' and normalize-space(.)='{{columnValue}}']" parameterized="true"/> - <element name="targetPathColumnValue" type="text" selector="//*[@id='urlrewriteGrid']//tbody//td[@data-column='target_path' and normalize-space(.)='{{columnValue}}']" parameterized="true"/> - <element name="searchButton" type="button" selector="//button[@data-ui-id='widget-button-1']" timeout="30"/> - <element name="resetButton" type="button" selector="button[data-ui-id='widget-button-0']" timeout="30"/> - <element name="emptyRecordMessage" type="text" selector="//*[@class='empty-text']"/> - <element name="targetPathColumn" type="text" selector="//tr[@data-role='row'][{{var1}}]/td[@data-column='target_path']" parameterized="true"/> - <element name="redirectTypeColumn" type="text" selector="//tr[@data-role='row'][{{var1}}]/td[@data-column='redirect_type']" parameterized="true"/> - <element name="requestPathColumn" type="text" selector="//tr[@data-role='row'][{{var1}}]/td[@data-column='request_path']" parameterized="true"/> - <element name="emptyRecords" type="text" selector="//td[@class='empty-text']"/> - <element name="successMessage" type="text" selector="#messages"/> - <element name="editButton" type="text" selector="//tr[@data-role='row'][{{rowNumber}}]/td/a[contains(.,'Edit')]" parameterized="true"/> - <element name="storeView" type="text" selector="//tr[@data-role='row'][{{var1}}]/td[@data-column='store_id']" parameterized="true"/> + <element name="rowSelectAction" type="button" selector="//*[@data-role='grid']//tbody//tr[{{row}}+1]//td[count(//*[@data-role='grid']//th[contains(., 'Action')]/preceding-sibling::th)+1]//button[contains(@class, 'action-select')]" parameterized="true" timeout="30"/> + <element name="rowEditAction" type="button" selector="//*[@data-role='grid']//tbody//tr[{{row}}+1]//td[count(//*[@data-role='grid']//th[contains(., 'Action')]/preceding-sibling::th)+1]//a[contains(., 'Edit')]" parameterized="true" timeout="30"/> + <element name="gridCellByColumnRowNumber" type="text" selector="//*[@data-role='grid']//tbody//tr[{{row}}+1]//td[count(//*[@data-role='grid']//th[contains(., '{{column}}')]/preceding-sibling::th)+1]" parameterized="true"/> + <element name="gridCellByColumnValue" type="text" selector="//*[@data-role='grid']//tbody//td[count(//*[@data-role='grid']//th[contains(., '{{column}}')]/preceding-sibling::th)+1][normalize-space(.)='{{columnValue}}']" parameterized="true"/> + <element name="select" type="button" selector="//*[@data-role='grid']//tbody//tr[{{row}}+1]//button[@class='action-select']" timeout="30" parameterized="true"/> + <element name="activeEdit" type="button" selector="//*[@data-role='grid']//tbody//ul[@class='action-menu _active']//a[@data-action='item-edit']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminAutoUpdateURLRewriteWhenCategoryIsDeletedTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminAutoUpdateURLRewriteWhenCategoryIsDeletedTest.xml index 022d28ed692c1..eae8c7f0838c4 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminAutoUpdateURLRewriteWhenCategoryIsDeletedTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminAutoUpdateURLRewriteWhenCategoryIsDeletedTest.xml @@ -26,7 +26,7 @@ </before> <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml index 77fb2b5285ac3..f635df7edb6f7 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml @@ -51,7 +51,7 @@ <argument name="name" value="productformagetwo68980"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersIfSet"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="SwitchCategoryStoreViewActionGroup" stepKey="switchToStoreViewEn"> <argument name="Store" value="customStoreENNotUnique.name"/> @@ -91,35 +91,47 @@ <grabFromCurrentUrl regex="~/id/(\d+)/~" stepKey="grabProductIdFromUrl"/> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="goToUrlRewritesIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-english.html" stepKey="inputCategoryUrlForENStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-english.html')}}" stepKey="seeUrlInRequestPathColumn"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-english.html" stepKey="inputCategoryUrlForENStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-english.html')}}" stepKey="seeUrlInRequestPathColumn"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-dutch.html" stepKey="inputCategoryUrlForNLStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-dutch.html')}}" stepKey="seeUrlInRequestPathColumn1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn1"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-dutch.html" stepKey="inputCategoryUrlForNLStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-dutch.html')}}" stepKey="seeUrlInRequestPathColumn1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn1"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue('catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn2"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters2"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters2"/> + <waitForPageLoad stepKey="waitForPageToLoad2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', 'catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView1"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue('catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn3"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters3"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView1"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters3"/> + <waitForPageLoad stepKey="waitForPageToLoad3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', 'catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn3"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-english/productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView2"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton4"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-english/productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn4"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn4"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters4"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-english/productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView2"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters4"/> + <waitForPageLoad stepKey="waitForPageToLoad4"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-english/productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn4"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn4"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-dutch/productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView3"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton5"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-dutch/productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn5"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn5"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters5"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-dutch/productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView3"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters5"/> + <waitForPageLoad stepKey="waitForPageToLoad5"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-dutch/productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn5"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn5"/> </test> <test name="AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTestWithConfigurationTurnedOff"> <annotations> @@ -175,7 +187,7 @@ <argument name="name" value="productformagetwo68980"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersIfSet"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="resetConfigurationSetting"/> <!--Flush cache--> <magentoCLI command="cache:flush" stepKey="cleanCache2"/> @@ -218,29 +230,37 @@ <grabFromCurrentUrl regex="~/id/(\d+)/~" stepKey="grabProductIdFromUrl"/> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="goToUrlRewritesIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-english.html" stepKey="inputCategoryUrlForENStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-english.html')}}" stepKey="seeUrlInRequestPathColumn"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-english.html" stepKey="inputCategoryUrlForENStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-english.html')}}" stepKey="seeUrlInRequestPathColumn"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="category-dutch.html" stepKey="inputCategoryUrlForNLStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-dutch.html')}}" stepKey="seeUrlInRequestPathColumn1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn1"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="category-dutch.html" stepKey="inputCategoryUrlForNLStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-dutch.html')}}" stepKey="seeUrlInRequestPathColumn1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/category/view/id/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn1"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue('catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn2"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-english/productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn4"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn4"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters2"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="productformagetwo68980-english.html" stepKey="inputProductUrlForENStoreView"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters2"/> + <waitForPageLoad stepKey="waitForPageToLoad2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', 'catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn2"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-english/productformagetwo68980-english.html')}}" stepKey="seeUrlInRequestPathColumn4"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn4"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView1"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue('catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn3"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue('category-dutch/productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn5"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.targetPathColumnValue(catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn5"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters3"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="productformagetwo68980-dutch.html" stepKey="inputProductUrlForENStoreView1"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters3"/> + <waitForPageLoad stepKey="waitForPageToLoad3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', 'catalog/product/view/id/$grabProductIdFromUrl')}}" stepKey="seeUrlInTargetPathColumn3"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', 'category-dutch/productformagetwo68980-dutch.html')}}" stepKey="seeUrlInRequestPathColumn5"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Target Path', catalog/product/view/id/$grabProductIdFromUrl/category/$$createCategory.id$$)}}" stepKey="seeUrlInTargetPathColumn5"/> <!-- Switch StoreView --> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnProduct4Page"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategory2Test.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategory2Test.xml index e14bb5342db91..7244ed1d6b534 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategory2Test.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategory2Test.xml @@ -45,7 +45,7 @@ <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearWebsitesGridFilters"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!-- On the categories editing page change store view to created additional view --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml index 7f9ee3020c388..cd17d169804db 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesInCatalogCategoriesAfterChangingUrlKeyForStoreViewAndMovingCategoryTest.xml @@ -48,7 +48,7 @@ <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreView"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- On the categories editing page change store view to created additional view --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddNoRedirectTest.xml index 732fc22aaf84a..339e078faa5a4 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddNoRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddNoRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Url Rewrite Index Page and update the Custom Url Rewrite, Store, Request Path, Redirect Type and Description --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddPermanentRedirectTest.xml index 867b3ee54161c..546637f2e548d 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddPermanentRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Url Rewrite Index Page and update the Custom Url Rewrite, Store, Request Path, Redirect Type and Description --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml index ab18add56aeb9..2ea04625b7d3d 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteRootCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open Url Rewrite Index Page and update the Custom Url Rewrite, Store, Request Path, Redirect Type and Description --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddPermanentRedirectTest.xml index bd4f7d7a32165..d0a744a168ce3 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddPermanentRedirectTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{defaultCmsPage.title}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open CMS Edit Page and Get the CMS ID --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddTemporaryRedirectTest.xml index 074140845c8a6..4327b02d396f9 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCMSPageUrlRewriteAndAddTemporaryRedirectTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{defaultCmsPage.title}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Open CMS Edit Page and Get the CMS ID --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCategoryUrlRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCategoryUrlRewriteAndAddPermanentRedirectTest.xml index cdd7c334e35cd..c70112c0953b3 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCategoryUrlRewriteAndAddPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomCategoryUrlRewriteAndAddPermanentRedirectTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{FirstLevelSubCat.name}}.html"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Open Category Page and Get Category ID --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomProductUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomProductUrlRewriteAndAddTemporaryRedirectTest.xml index 593c4282fc516..c39bae9fd2ff2 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomProductUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateCustomProductUrlRewriteAndAddTemporaryRedirectTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{_defaultProduct.name}}.html"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter Product in product page and get the Product ID --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteAndAddNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteAndAddNoRedirectTest.xml index c51030315b287..36c25d9a21685 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteAndAddNoRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteAndAddNoRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteWithCategoryAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteWithCategoryAndAddTemporaryRedirectTest.xml index d433aa7557094..92a2b6cac6b16 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteWithCategoryAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductURLRewriteWithCategoryAndAddTemporaryRedirectTest.xml @@ -27,7 +27,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddPermanentRedirectTest.xml index e1ff4f598943e..b03912728a3d9 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddPermanentRedirectTest.xml @@ -22,7 +22,7 @@ </before> <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddTemporaryRedirectTest.xml index 3fa4e6b7bad90..4b03d28d44867 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductUrLRewriteAndAddTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml index 38a84f6a75f30..653995da1a3a8 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCreateProductWithSeveralWebsitesAndCheckURLRewritesTest.xml @@ -35,7 +35,7 @@ </actionGroup> <deleteData stepKey="deleteRootCategory" createDataKey="rootCategory"/> <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create first store --> @@ -95,8 +95,8 @@ <argument name="redirectType" value="No"/> <argument name="targetPath" value="catalog/category/view/id/{$categoryId}"/> </actionGroup> - <see selector="{{AdminUrlRewriteIndexSection.storeView('1')}}" userInput="{{customStoreGroup.name}}" stepKey="seeStoreValueForCategoryId"/> - <see selector="{{AdminUrlRewriteIndexSection.storeView('1')}}" userInput="{{customStoreEN.name}}" stepKey="seeStoreViewValueForCategoryId"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Store View')}}" userInput="{{customStoreGroup.name}}" stepKey="seeStoreValueForCategoryId"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Store View')}}" userInput="{{customStoreEN.name}}" stepKey="seeStoreViewValueForCategoryId"/> <!-- Grab product Id --> <actionGroup ref="FilterAndSelectProductActionGroup" stepKey="grabProductId"> @@ -109,7 +109,7 @@ <argument name="redirectType" value="No"/> <argument name="targetPath" value="catalog/product/view/id/{$productId}"/> </actionGroup> - <see selector="{{AdminUrlRewriteIndexSection.storeView('1')}}" userInput="{{customStore.name}}" stepKey="seeStoreValueForProductId"/> - <see selector="{{AdminUrlRewriteIndexSection.storeView('1')}}" userInput="{{storeViewData.name}}" stepKey="seeStoreViewValueForProductId"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Store View')}}" userInput="{{customStore.name}}" stepKey="seeStoreValueForProductId"/> + <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Store View')}}" userInput="{{storeViewData.name}}" stepKey="seeStoreViewValueForProductId"/> </test> </tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageNoRedirectUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageNoRedirectUrlRewriteTest.xml new file mode 100644 index 0000000000000..a65efce1a48ea --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageNoRedirectUrlRewriteTest.xml @@ -0,0 +1,57 @@ +<?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="AdminDeleteCMSPageNoRedirectUrlRewriteTest"> + <annotations> + <stories value="Delete CMS Page No Redirect URL rewrite"/> + <title value="Delete CMS Page No Redirect URL rewrite"/> + <description value="Login as Admin and remove CMS Page Url Rewrite"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Assert initial CMS page Url Rewrite in Grid--> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath1"> + <argument name="redirectPath" value="$$createCMSPage.identifier$$"/> + <argument name="redirectType" value="No"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert initial request path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront1"> + <argument name="page" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!--Delete created cms page url rewrite and verify AssertUrlRewriteDeletedMessage--> + <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteUrlRewrite"> + <argument name="requestPath" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchDeletedUrlRewriteInGrid"> + <argument name="requestPath" value="$$createCMSPage.identifier$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPagePermanentRedirectUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPagePermanentRedirectUrlRewriteTest.xml new file mode 100644 index 0000000000000..fa19b2a30c2cd --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPagePermanentRedirectUrlRewriteTest.xml @@ -0,0 +1,98 @@ +<?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="AdminDeleteCMSPagePermanentRedirectUrlRewriteTest"> + <annotations> + <stories value="Delete CMS Page Permanent Redirect URL rewrite"/> + <title value="Delete CMS Page Permanent Redirect URL rewrite"/> + <description value="Login as Admin and create custom CMS page UrlRewrite and add Permanent redirect type and delete Permanent redirect URL rewrite"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Open UrlRewrite Edit page and update the fields and fill the created CMS Page Target Path --> + <actionGroup ref="AdminAddCustomUrlRewriteActionGroup" stepKey="addCustomUrlRewrite"> + <argument name="customUrlRewriteValue" value="Custom"/> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectTypeValue" value="Permanent (301)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + <argument name="description" value="Created New CMS Page."/> + </actionGroup> + + <!-- Assert updated CMS page Url Rewrite in Grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath"> + <argument name="redirectPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectType" value="Permanent (301)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert initial CMS page Url Rewrite in Grid--> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath1"> + <argument name="redirectPath" value="$$createCMSPage.identifier$$"/> + <argument name="redirectType" value="No"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert added Request Path redirects to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront"> + <argument name="page" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!-- Assert added CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + + <!-- Assert initial request path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront1"> + <argument name="page" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!-- Assert initial CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage1"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + + <!--Delete added CMS Page Url Rewrite and verify AssertUrlRewriteDeletedMessage--> + <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteUrlRewrite"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchDeletedUrlRewriteInGrid"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!--Verify AssertPageByUrlRewriteIsNotFound--> + <actionGroup ref="AssertPageByUrlRewriteIsNotFoundActionGroup" stepKey="amOnPage"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageTemporaryRedirectUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageTemporaryRedirectUrlRewriteTest.xml new file mode 100644 index 0000000000000..2bed25aa3f39d --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCMSPageTemporaryRedirectUrlRewriteTest.xml @@ -0,0 +1,98 @@ +<?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="AdminDeleteCMSPageTemporaryRedirectUrlRewriteTest"> + <annotations> + <stories value="Delete CMS Page Temporary Redirect URL rewrite"/> + <title value="Delete CMS Page Temporary Redirect URL rewrite"/> + <description value="Login as Admin and create custom CMS page UrlRewrite and add Temporary redirect type and delete Temporary redirect URL rewrite"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Open UrlRewrite Edit page and update the fields and fill the created CMS Page Target Path --> + <actionGroup ref="AdminAddCustomUrlRewriteActionGroup" stepKey="addCustomUrlRewrite"> + <argument name="customUrlRewriteValue" value="Custom"/> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectTypeValue" value="Temporary (302)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + <argument name="description" value="Created New CMS Page."/> + </actionGroup> + + <!-- Assert updated CMS page Url Rewrite in Grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath"> + <argument name="redirectPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectType" value="Temporary (302)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert initial CMS page Url Rewrite in Grid--> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByRequestPath1"> + <argument name="redirectPath" value="$$createCMSPage.identifier$$"/> + <argument name="redirectType" value="No"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert Updated Request Path redirects to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront"> + <argument name="page" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!-- Assert updated CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + + <!-- Assert initial request path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront1"> + <argument name="page" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!-- Assert initial CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage1"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + + <!--Delete added CMS Page Url Rewrite and verify AssertUrlRewriteDeletedMessage--> + <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteUrlRewrite"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchDeletedUrlRewriteInGrid"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!--Verify AssertPageByUrlRewriteIsNotFound--> + <actionGroup ref="AssertPageByUrlRewriteIsNotFoundActionGroup" stepKey="amOnPage"> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml index ad952225c2ff5..fe71094e49064 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create the Category Url Rewrite--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteTest.xml new file mode 100644 index 0000000000000..b781a8297499c --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteTest.xml @@ -0,0 +1,56 @@ +<?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="AdminDeleteCategoryUrlRewriteTest"> + <annotations> + <stories value="Delete Category URL rewrite"/> + <title value="Delete Category URL rewrite"/> + <description value="Test log in to URL rewrite and Delete Category URL rewrite"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <createData entity="_defaultCategory" stepKey="category"/> + </before> + <after> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open Url Rewrite Index Page and update the Category Url Rewrite, Store, Request Path, Redirect Type and Description --> + <actionGroup ref="AdminAddUrlRewriteActionGroup" stepKey="addUrlRewrite"> + <argument name="category" value="$$category.name$$"/> + <argument name="customUrlRewriteValue" value="For Category'"/> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="newcategoryrequestpath.html"/> + <argument name="redirectTypeValue" value="No"/> + <argument name="description" value="End To End Test"/> + </actionGroup> + + <!-- Get Category ID --> + <actionGroup ref="OpenCategoryFromCategoryTreeActionGroup" stepKey="getCategoryId"> + <argument name="category" value="$$category.name$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="categoryId" regex="#\/([0-9]*)?\/$#"/> + + <!--Delete created product url rewrite and verify AssertUrlRewriteDeletedMessage--> + <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteUrlRewrite"> + <argument name="requestPath" value="newcategoryrequestpath.html"/> + </actionGroup> + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchDeletedUrlRewriteInGrid"> + <argument name="requestPath" value="newcategoryrequestpath.html"/> + </actionGroup> + <!--Verify AssertPageByUrlRewriteIsNotFound--> + <actionGroup ref="AssertPageByUrlRewriteIsNotFoundActionGroup" stepKey="amOnPage"> + <argument name="requestPath" value="newcategoryrequestpath.html"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml index dc9928773bf35..06b5745c32be3 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create the Category Url Rewrite--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml index e2f0d6af0deab..d58560e40533e 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminGoToAddNewUrlRewritePageActionGroup" stepKey="openUrlRewriteEditPage"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithPermanentRedirectTest.xml index 741be6985d517..989aa277f7de1 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithPermanentRedirectTest.xml @@ -14,6 +14,7 @@ <title value="Delete CMS Page URL rewrite with Permanent Redirect"/> <description value="Log in to admin and delete CMS Page URL rewrite with Permanent Redirect"/> <testCaseId value="MC-14649"/> + <severity value="CRITICAL"/> <group value="mtf_migrated"/> </annotations> <before> @@ -22,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminGoToAddNewUrlRewritePageActionGroup" stepKey="openUrlRewriteEditPage"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml index e3d417f3c1f39..a81c00506c671 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminGoToAddNewUrlRewritePageActionGroup" stepKey="openUrlRewriteEditPage"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCustomUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCustomUrlRewriteTest.xml index 288c32102c606..c03c21abb9e7e 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCustomUrlRewriteTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCustomUrlRewriteTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Delete created custom url rewrite and verify AssertUrlRewriteDeletedMessage--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductURLRewriteEntityTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductURLRewriteEntityTest.xml index 2becb177ee72b..6803816f42d85 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductURLRewriteEntityTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductURLRewriteEntityTest.xml @@ -28,7 +28,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter and Select the created Product --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductUrlRewriteTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductUrlRewriteTest.xml new file mode 100644 index 0000000000000..8ebad9656e7af --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteProductUrlRewriteTest.xml @@ -0,0 +1,42 @@ +<?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="AdminDeleteProductUrlRewriteTest"> + <annotations> + <stories value="Delete Product URL rewrite"/> + <title value="Delete Product URL rewrite"/> + <description value="Test log in to URL rewrite and Delete Product URL rewrite"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + </before> + <after> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Delete created product url rewrite and verify AssertUrlRewriteDeletedMessage--> + <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteUrlRewrite"> + <argument name="requestPath" value="$$simpleProduct.custom_attributes[url_key]$$.html"/> + </actionGroup> + + <!--Search and verify AssertUrlRewriteNotInGrid--> + <actionGroup ref="AdminSearchDeletedUrlRewriteActionGroup" stepKey="searchDeletedUrlRewriteInGrid"> + <argument name="requestPath" value="$$simpleProduct.custom_attributes[url_key]$$.html"/> + </actionGroup> + + <!--Verify AssertPageByUrlRewriteIsNotFound--> + <actionGroup ref="AssertPageByUrlRewriteIsNotFoundActionGroup" stepKey="amOnPage"> + <argument name="requestPath" value="$$simpleProduct.custom_attributes[url_key]$$.html"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminGenerateUrlRewritesForProductInCategoriesSwitchOffTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminGenerateUrlRewritesForProductInCategoriesSwitchOffTest.xml index 884c7778786a3..63e76717dd6b6 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminGenerateUrlRewritesForProductInCategoriesSwitchOffTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminGenerateUrlRewritesForProductInCategoriesSwitchOffTest.xml @@ -40,15 +40,17 @@ <!--Flush cache--> <magentoCLI command="cache:flush" stepKey="cleanCache1"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createCategory.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createCategory.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> <!-- 2. Set the configuration for Generate "category/product" URL Rewrites to No--> <amOnPage url="{{CatalogConfigPage.url}}" stepKey="amOnCatalogConfigPage"/> @@ -65,9 +67,11 @@ <!-- 4. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName2"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createCategory.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="dontSeeValue2"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName2"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createCategory.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="dontSeeValue2"/> </test> </tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminMarketingUrlRewritesNavigateMenuTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminMarketingUrlRewritesNavigateMenuTest.xml index 443307b427b42..51561cfcb220f 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminMarketingUrlRewritesNavigateMenuTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminMarketingUrlRewritesNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToMarketingURLRewritesPage"> <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminProductCreateUrlRewriteForCustomStoreViewTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminProductCreateUrlRewriteForCustomStoreViewTest.xml index 0ad68dae4e4ce..f3b0ca2237975 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminProductCreateUrlRewriteForCustomStoreViewTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminProductCreateUrlRewriteForCustomStoreViewTest.xml @@ -41,7 +41,7 @@ <argument name="customStore" value="customStore"/> </actionGroup> <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearFilterForStores"/> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <!--Step 1. Navigate as Admin on Product Page for edit product`s Url Key--> <actionGroup ref="NavigateToCreatedProductEditPageActionGroup" stepKey="goToProductForUrlRewrite"> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddAspxRequestPathTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddAspxRequestPathTest.xml index fb8f200741c8a..21b0486bd1aad 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddAspxRequestPathTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddAspxRequestPathTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search and Select Edit option for created category in grid --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddNoRedirectTest.xml index 72180105b38f8..7edeba336a7e9 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddNoRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddNoRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search and Select Edit option for created category in grid --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddPermanentRedirectTest.xml index 3fb8e5da39caf..a91da90581dda 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddPermanentRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddPermanentRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search and Select Edit option for created category in grid --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml index bea5c44461a70..e49318af53639 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCategoryUrlRewriteAndAddTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="category" stepKey="deleteCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search and Select Edit option for created category in grid --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml index b2fa13ead1164..c47419eee28e0 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create Custom Store View--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithPermanentReirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithPermanentReirectTest.xml index 3bf278db8410a..510b2f5607df7 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithPermanentReirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithPermanentReirectTest.xml @@ -12,6 +12,7 @@ <stories value="Update CMS Page URL Redirect With Permanent Redirect"/> <title value="Update CMS Page URL Redirect With Permanent Redirect"/> <description value="Login as Admin and tried to update the created URL Rewrite for CMS page"/> + <severity value="CRITICAL"/> <group value="cMSContent"/> <group value="mtf_migrated"/> </annotations> @@ -22,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create Custom Store View--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml index b00241bc3acac..b696811cfa8c9 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Create Custom Store View--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddNoRedirectTest.xml new file mode 100644 index 0000000000000..b04d417cf7efa --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddNoRedirectTest.xml @@ -0,0 +1,66 @@ +<?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="AdminUpdateCmsPageUrlRewriteAndAddNoRedirectTest"> + <annotations> + <stories value="Update URL rewrite"/> + <title value="Update Cms Page URL Rewrites, no redirect type"/> + <description value="Login as Admin and update Cms Page Url Rewrite and add redirect type No"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Search and Select Edit option for created cms page in grid --> + <actionGroup ref="AdminSearchAndSelectUrlRewriteInGridActionGroup" stepKey="editUrlRewrite"> + <argument name="requestPath" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!-- Open UrlRewrite Edit page and update the fields --> + <actionGroup ref="AdminUpdateUrlRewriteActionGroup" stepKey="updateCmsPageUrlRewrite"> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectTypeValue" value="No"/> + <argument name="description" value="Update Cms Page Url Rewrite"/> + </actionGroup> + + <!-- Assert Cms Page Url Rewrite in grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByNewRequestPath"> + <argument name="redirectPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectType" value="No"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert Updated Request Path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront"> + <argument name="page" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!-- Assert updated CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddPermanentRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddPermanentRedirectTest.xml new file mode 100644 index 0000000000000..138b5f280d5f2 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddPermanentRedirectTest.xml @@ -0,0 +1,66 @@ +<?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="AdminUpdateCmsPageUrlRewriteAndAddPermanentRedirectTest"> + <annotations> + <stories value="Update URL rewrite"/> + <title value="Update Cms Page URL Rewrites, Permanent redirect type"/> + <description value="Login as Admin and update Cms Page Url Rewrite and add Permanent redirect type"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Search and Select Edit option for created cms page in grid --> + <actionGroup ref="AdminSearchAndSelectUrlRewriteInGridActionGroup" stepKey="editUrlRewrite"> + <argument name="requestPath" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!-- Open UrlRewrite Edit page and update the fields --> + <actionGroup ref="AdminUpdateUrlRewriteActionGroup" stepKey="updateCmsPageUrlRewrite"> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectTypeValue" value="Permanent (301)"/> + <argument name="description" value="Update Cms Page Url Rewrite"/> + </actionGroup> + + <!-- Assert Cms Page Url Rewrite in grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByNewRequestPath"> + <argument name="redirectPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectType" value="Permanent (301)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert Updated Request Path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront"> + <argument name="page" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!-- Assert updated CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddTemporaryRedirectTest.xml new file mode 100644 index 0000000000000..d996f2e3c7bb9 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageUrlRewriteAndAddTemporaryRedirectTest.xml @@ -0,0 +1,66 @@ +<?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="AdminUpdateCmsPageUrlRewriteAndAddTemporaryRedirectTest"> + <annotations> + <stories value="Update URL rewrite"/> + <title value="Update Cms Page URL Rewrites, Temporary redirect type"/> + <description value="Login as Admin and update Cms Page Url Rewrite and add Temporary redirect type"/> + <testCaseId value=""/> + <severity value="CRITICAL"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <createData entity="simpleCmsPage" stepKey="createCMSPage"/> + </before> + <after> + <deleteData createDataKey="createCMSPage" stepKey="deleteCMSPage"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Open CMS Edit Page and Get the CMS ID --> + <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> + <argument name="CMSPage" value="$$createCMSPage$$"/> + </actionGroup> + <grabFromCurrentUrl stepKey="cmsId" regex="#\/([0-9]*)?\/$#"/> + + <!-- Search and Select Edit option for created cms page in grid --> + <actionGroup ref="AdminSearchAndSelectUrlRewriteInGridActionGroup" stepKey="editUrlRewrite"> + <argument name="requestPath" value="$$createCMSPage.identifier$$"/> + </actionGroup> + + <!-- Open UrlRewrite Edit page and update the fields --> + <actionGroup ref="AdminUpdateUrlRewriteActionGroup" stepKey="updateCmsPageUrlRewrite"> + <argument name="storeValue" value="Default Store View"/> + <argument name="requestPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectTypeValue" value="Temporary (302)"/> + <argument name="description" value="Update Cms Page Url Rewrite"/> + </actionGroup> + + <!-- Assert Cms Page Url Rewrite in grid --> + <actionGroup ref="AdminSearchByRequestPathActionGroup" stepKey="searchByNewRequestPath"> + <argument name="redirectPath" value="{{defaultCmsPage.title}}"/> + <argument name="redirectType" value="Temporary (302)"/> + <argument name="targetPath" value="cms/page/view/page_id/{$cmsId}"/> + </actionGroup> + + <!-- Assert Updated Request Path directs to the CMS Page on Store Front --> + <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront"> + <argument name="page" value="{{defaultCmsPage.title}}"/> + </actionGroup> + + <!-- Assert updated CMS redirect in Store Front --> + <actionGroup ref="AssertStoreFrontCMSPageActionGroup" stepKey="assertCMSPage"> + <argument name="cmsTitle" value="$$createCMSPage.title$$"/> + <argument name="cmsContent" value="$$createCMSPage.content$$"/> + <argument name="cmsContentHeading" value="$$createCMSPage.content_heading$$"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesPermanentTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesPermanentTest.xml index a07f7b8c0fe60..79376dfd7be35 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesPermanentTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesPermanentTest.xml @@ -26,7 +26,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{customPermanentUrlRewrite.request_path}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Search default custom url rewrite in grid--> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesTemporaryTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesTemporaryTest.xml index dcf923a34081b..9253cad21f936 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesTemporaryTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCustomURLRewritesTemporaryTest.xml @@ -28,7 +28,7 @@ <actionGroup ref="AdminDeleteUrlRewriteActionGroup" stepKey="deleteCustomUrlRewrite"> <argument name="requestPath" value="{{customTemporaryUrlRewrite.request_path}}"/> </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Filter Product in product page and get the Product ID --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateProductUrlRewriteAndAddTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateProductUrlRewriteAndAddTemporaryRedirectTest.xml index 74f3a60f35cea..e70896b7de04f 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateProductUrlRewriteAndAddTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateProductUrlRewriteAndAddTemporaryRedirectTest.xml @@ -23,7 +23,7 @@ </before> <after> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Search and Select Edit option for created product in grid --> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml index 9fcca06df5c69..2a0152c9da34c 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml @@ -51,12 +51,13 @@ <comment userInput="2. Open Marketing - SEO and Search - URL Rewrites " stepKey="commentVerifyUrlRewrite" /> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> <comment userInput="3. Import products with add/update behavior " stepKey="commentProductImport" /> <actionGroup ref="AdminImportProductsActionGroup" stepKey="adminImportProducts"> @@ -72,14 +73,15 @@ <comment userInput="5. Open Marketing - SEO and Search - URL Rewrites" stepKey="commentVerifyURLAfterImport" /> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$-new.html" stepKey="inputProductName2"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters2"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$-new.html" stepKey="inputProductName2"/> <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue4"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue5"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue6"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue7"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue4"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue5"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue6"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$-new.html)}}" stepKey="seeInListValue7"/> </test> </tests> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductInAnchorCategoriesTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductInAnchorCategoriesTest.xml index dc82a3e4ab24f..497ab653a0594 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductInAnchorCategoriesTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductInAnchorCategoriesTest.xml @@ -46,12 +46,14 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- 2. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> <!-- 3. Edit Category 1 for DEFAULT Store View: --> <actionGroup ref="SwitchCategoryStoreViewActionGroup" stepKey="switchStoreView"> @@ -68,15 +70,17 @@ <!-- 5. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName2"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue3"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue4"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue5"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue6"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue7"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName2"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue2"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue3"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue4"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue5"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue6"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue7"/> </test> <test name="AdminUrlRewritesForProductInAnchorCategoriesTestWithConfigurationTurnedOff"> @@ -129,12 +133,14 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- 2. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue1"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue2"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue3"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeValue4"/> <!-- 3. Edit Category 1 for DEFAULT Store View: --> <actionGroup ref="SwitchCategoryStoreViewActionGroup" stepKey="switchStoreView"> @@ -151,15 +157,17 @@ <!-- 5. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage2"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName2"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton2"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue2"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue3"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue4"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue5"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue6"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue7"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName1"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue1"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue2"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue3"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue4"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue5"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue6"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$-new/$simpleSubCategory2.custom_attributes[url_key]$/$simpleSubCategory3.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeInListValue7"/> <amOnPage url="/$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="navigateToProductPage"/> <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductName"/> @@ -271,10 +279,12 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!-- 2. Open Marketing - SEO & Search - URL Rewrites --> <amOnPage url="{{AdminUrlRewriteIndexPage.url}}" stepKey="amOnUrlRewriteIndexPage"/> - <fillField selector="{{AdminUrlRewriteIndexSection.requestPathFilter}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName5"/> - <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickSearchButton5"/> - <seeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeProducturl"/> - <dontSeeElement selector="{{AdminUrlRewriteIndexSection.requestPathColumnValue($simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="dontSeeCategoryProducturlKey"/> + <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters"/> + <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="inputProductName"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <waitForPageLoad stepKey="waitForPageToLoad"/> + <seeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="seeProducturl"/> + <dontSeeElement selector="{{AdminUrlRewriteIndexSection.gridCellByColumnValue('Request Path', $simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html)}}" stepKey="dontSeeCategoryProducturlKey"/> <amOnPage url="/$simpleSubCategory1.custom_attributes[url_key]$/$createSimpleProduct.custom_attributes[url_key]$.html" stepKey="navigateToProductPage"/> <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductName"/> </test> diff --git a/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/InlineEditTest.php b/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/InlineEditTest.php new file mode 100644 index 0000000000000..9fd4a022061cb --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/InlineEditTest.php @@ -0,0 +1,302 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewrite\Test\Unit\Controller\Url\Rewrite; + +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Controller\Result\Json; +use Magento\Framework\Controller\Result\JsonFactory; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite\InlineEdit; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewrite as UrlRewriteResource; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteFactory as UrlRewriteResourceFactory; +use Magento\UrlRewrite\Model\UrlRewrite; +use Magento\UrlRewrite\Model\UrlRewriteFactory; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Url rewrite inline edit action unit test class + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class InlineEditTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var RequestInterface|MockObject + */ + private $request; + + /** + * @var Context|MockObject + */ + private $contextMock; + + /** + * @var JsonFactory|MockObject + */ + private $jsonFactory; + + /** + * @var Json|MockObject + */ + private $resultJson; + + /** + * @var UrlRewrite|MockObject + */ + private $urlRewrite; + + /** + * @var UrlRewriteFactory|MockObject + */ + private $urlRewriteFactory; + + /** + * @var UrlRewriteResource|MockObject + */ + private $urlRewriteResource; + + /** + * @var urlRewriteResourceFactory|MockObject + */ + private $urlRewriteResourceFactory; + + /** + * @var InlineEdit|MockObject + */ + private $inlineEditController; + + /** + * SetUp method + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + + $this->request = $this->getMockForAbstractClass( + RequestInterface::class, + [], + '', + false + ); + + $this->contextMock = $this->objectManager->getObject( + Context::class, + [ + 'request' => $this->request + ] + ); + + $this->resultJson = $this->createMock(Json::class); + $this->jsonFactory = $this->createPartialMock( + JsonFactory::class, + ['create'] + ); + + $this->urlRewrite = $this->createPartialMock( + UrlRewrite::class, + ['addData', 'getId'] + ); + $this->urlRewriteFactory = $this->createPartialMock( + UrlRewriteFactory::class, + ['create'] + ); + + $this->urlRewriteResource = $this->createPartialMock( + UrlRewriteResource::class, + ['load', 'save'] + ); + $this->urlRewriteResourceFactory = $this->createPartialMock( + urlRewriteResourceFactory::class, + ['create'] + ); + + $this->inlineEditController = $this->objectManager->getObject( + InlineEdit::class, + [ + 'context' => $this->contextMock, + 'urlRewriteFactory' => $this->urlRewriteFactory, + 'urlRewriteResourceFactory' => $this->urlRewriteResourceFactory, + 'jsonFactory' => $this->jsonFactory + ] + ); + } + + /** + * Prepare mocks for tests + * + * @return void + */ + private function prepareMocksWithParamsForTestExecute(): void + { + $postData = [ + 1 => [ + 'request_path' => 'category-1.html', + 'redirect_type' => 0, + 'url_rewrite_id' => 1 + ] + ]; + $this->request->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['isAjax', null, true], + ['items', [], $postData] + ] + ); + + $this->jsonFactory->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + + $this->urlRewriteResourceFactory->expects($this->once()) + ->method('create') + ->willReturn($this->urlRewriteResource); + + $this->urlRewriteResource->expects($this->once()) + ->method('load') + ->with($this->urlRewrite, 1) + ->willReturn($this->urlRewrite); + + $this->urlRewriteFactory->expects($this->once()) + ->method('create') + ->willReturn($this->urlRewrite); + + $this->urlRewrite->expects($this->once()) + ->method('addData') + ->with(array_shift($postData)) + ->willReturnSelf(); + } + + /** + * Execute test with runtime exception + * + * @return void + */ + public function testExecuteWithRuntimeException(): void + { + $this->prepareMocksWithParamsForTestExecute(); + $this->urlRewrite->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->urlRewriteResource->expects($this->once()) + ->method('save') + ->with($this->urlRewrite) + ->willThrowException(new \RuntimeException('RuntimeException')); + $this->resultJson->expects($this->once()) + ->method('setData') + ->with( + [ + 'messages' => [ + '[Url rewrite ID: 1] RuntimeException' + ], + 'error' => true + ] + ) + ->willReturnSelf(); + + $this->assertSame($this->resultJson, $this->inlineEditController->execute()); + } + + /** + * Execute test with exception + * + * @return void + */ + public function testExecuteWithException(): void + { + $this->prepareMocksWithParamsForTestExecute(); + $this->urlRewrite->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->urlRewriteResource->expects($this->once()) + ->method('save') + ->with($this->urlRewrite) + ->willThrowException(new \Exception('Exception')); + $this->resultJson->expects($this->once()) + ->method('setData') + ->with( + [ + 'messages' => [ + '[Url rewrite ID: 1] Something went wrong while saving the url rewrite.' + ], + 'error' => true + ] + ) + ->willReturnSelf(); + + $this->assertSame($this->resultJson, $this->inlineEditController->execute()); + } + + /** + * Execute test without post data + * + * @return void + */ + public function testExecuteWithoutData(): void + { + $this->jsonFactory->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + $this->request->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['isAjax', null, true], + ['items', [], []] + ] + ); + $this->resultJson->expects($this->once()) + ->method('setData') + ->with( + [ + 'messages' => [ + __('Please correct the data sent.') + ], + 'error' => true + ] + ) + ->willReturnSelf(); + + $this->assertSame($this->resultJson, $this->inlineEditController->execute()); + } + + /** + * Execute test without exceptions + * + * @return void + */ + public function testExecuteAction(): void + { + $this->prepareMocksWithParamsForTestExecute(); + $this->urlRewriteResource->expects($this->once()) + ->method('save') + ->with($this->urlRewrite) + ->willReturnSelf(); + $this->resultJson->expects($this->once()) + ->method('setData') + ->with( + [ + 'messages' => [], + 'error' => false + ] + ) + ->willReturnSelf(); + + $this->assertSame( + $this->resultJson, + $this->inlineEditController->execute() + ); + } +} diff --git a/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/MassDeleteTest.php b/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/MassDeleteTest.php new file mode 100644 index 0000000000000..bf58fe3d7067a --- /dev/null +++ b/app/code/Magento/UrlRewrite/Test/Unit/Controller/Url/Rewrite/MassDeleteTest.php @@ -0,0 +1,186 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewrite\Test\Unit\Controller\Url\Rewrite; + +use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; +use Magento\Framework\Controller\Result\RedirectFactory; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Ui\Component\MassAction\Filter; +use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite\MassDelete; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection as Collection; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory as CollectionFactory; +use Magento\UrlRewrite\Model\UrlRewrite; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Url rewrite mass delete action unit test class + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MassDeleteTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ManagerInterface|MockObject + */ + private $messageManagerMock; + + /** + * @var RedirectFactory|MockObject + */ + private $resultRedirectMock; + + /** + * @var Context|MockObject + */ + private $contextMock; + + /** + * @var Filter|MockObject + */ + private $filterMock; + + /** + * @var Collection|MockObject + */ + private $urlRewriteCollectionMock; + + /** + * @var CollectionFactory|MockObject + */ + private $collectionFactoryMock; + + /** + * @var MassDelete|object + */ + private $massDeleteController; + + /** + * @var RedirectFactory|MockObject + */ + private $resultRedirectFactoryMock; + + /** + * SetUp method + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + + $this->messageManagerMock = $this->createMock(ManagerInterface::class); + + $this->resultRedirectFactoryMock = $this->createPartialMock( + RedirectFactory::class, + ['create'] + ); + $this->resultRedirectMock = $this->createMock(Redirect::class); + + $this->contextMock = $this->createMock(Context::class); + + $this->filterMock = $this->getMockBuilder(Filter::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->contextMock->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManagerMock); + $this->contextMock->expects($this->any()) + ->method('getResultRedirectFactory') + ->willReturn($this->resultRedirectFactoryMock); + + $this->collectionFactoryMock = $this->createPartialMock( + CollectionFactory::class, + ['create'] + ); + $this->urlRewriteCollectionMock = + $this->createMock(Collection::class); + + $this->massDeleteController = $this->objectManager->getObject( + MassDelete::class, + [ + 'context' => $this->contextMock, + 'filter' => $this->filterMock, + 'collectionFactory' => $this->collectionFactoryMock + ] + ); + } + + /** + * Test mass delete action + * + * @throws LocalizedException + */ + public function testMassDeleteAction(): void + { + $collection = [ + $this->getUrlRewriteMock(), + $this->getUrlRewriteMock(), + $this->getUrlRewriteMock(true) + ]; + + $this->collectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->urlRewriteCollectionMock); + + $this->filterMock->expects($this->once()) + ->method('getCollection') + ->with($this->urlRewriteCollectionMock) + ->willReturn($this->urlRewriteCollectionMock); + + $this->urlRewriteCollectionMock->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator($collection)); + + $this->messageManagerMock->expects($this->once()) + ->method('addSuccessMessage') + ->with(__('A total of %1 record(s) have been deleted.', 2)); + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with(__('A total of %1 record(s) haven\'t been deleted.', 1)); + + $this->resultRedirectFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->resultRedirectMock); + $this->resultRedirectMock->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->assertSame($this->resultRedirectMock, $this->massDeleteController->execute()); + } + + /** + * Create url rewrite model mock + * + * @param bool $exception + * @return MockObject + */ + private function getUrlRewriteMock($exception = false): MockObject + { + $urlRewrite = $this->createPartialMock(UrlRewrite::class, ['delete']); + $urlRewriteInvocationMocker = $urlRewrite->expects($this->once()) + ->method('delete'); + if ($exception) { + $urlRewriteInvocationMocker->willThrowException( + new \Exception('Test delete exception') + ); + } else { + $urlRewriteInvocationMocker->willReturn(true); + } + + return $urlRewrite; + } +} diff --git a/app/code/Magento/UrlRewrite/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/UrlRewrite/Ui/Component/Listing/Column/BlockActions.php new file mode 100644 index 0000000000000..1e6dcde123129 --- /dev/null +++ b/app/code/Magento/UrlRewrite/Ui/Component/Listing/Column/BlockActions.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\UrlRewrite\Ui\Component\Listing\Column; + +use Magento\Framework\UrlInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Ui\Component\Listing\Columns\Column; + +/** + * Class EditAction + */ +class BlockActions extends Column +{ + /** + * @var UrlInterface + */ + private $urlBuilder; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UrlInterface $urlBuilder + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + UrlInterface $urlBuilder, + array $components = [], + array $data = [] + ) { + $this->urlBuilder = $urlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * Prepare Data Source + * + * @param array $dataSource + * @return array + */ + public function prepareDataSource(array $dataSource): array + { + if (isset($dataSource['data']['items'])) { + foreach ($dataSource['data']['items'] as & $item) { + if (isset($item['url_rewrite_id'])) { + $editUrlPath = $this->getData('config/editUrlPath') ?: '#'; + $deleteUrlPath = $this->getData('config/deleteUrlPath') ?: '#'; + $urlEntityParamName = $this->getData('config/urlEntityParamName') ?: 'url_rewrite_id'; + $title = $item['url_rewrite_id']; + $item[$this->getData('name')] = [ + 'edit' => [ + 'href' => $this->urlBuilder->getUrl( + $editUrlPath, + [ + $urlEntityParamName => $item['url_rewrite_id'] + ] + ), + 'label' => __('Edit') + ], + 'delete' => [ + 'href' => $this->urlBuilder->getUrl( + $deleteUrlPath, + [ + $urlEntityParamName => $item['url_rewrite_id'] + ] + ), + 'label' => __('Delete'), + 'confirm' => [ + 'title' => __('Delete record #%1', $title), + 'message' => __('Are you sure you want to delete a record #%1?', $title) + ], + 'post' => true + ] + ]; + } + } + } + + return $dataSource; + } +} diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json index 90f11accfe503..083a32f43bd49 100644 --- a/app/code/Magento/UrlRewrite/composer.json +++ b/app/code/Magento/UrlRewrite/composer.json @@ -12,7 +12,8 @@ "magento/module-catalog-url-rewrite": "*", "magento/module-cms": "*", "magento/module-cms-url-rewrite": "*", - "magento/module-store": "*" + "magento/module-store": "*", + "magento/module-ui": "*" }, "type": "magento2-module", "license": [ diff --git a/app/code/Magento/UrlRewrite/etc/di.xml b/app/code/Magento/UrlRewrite/etc/di.xml index e09c48ff89141..e56ef7b6c467d 100644 --- a/app/code/Magento/UrlRewrite/etc/di.xml +++ b/app/code/Magento/UrlRewrite/etc/di.xml @@ -26,4 +26,18 @@ </argument> </arguments> </type> + <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> + <arguments> + <argument name="collections" xsi:type="array"> + <item name="url_rewrite_listing_data_source" xsi:type="string">Magento\UrlRewrite\Ui\Component\UrlRewrite\DataProvider\SearchResult</item> + </argument> + </arguments> + </type> + <virtualType name="Magento\UrlRewrite\Ui\Component\UrlRewrite\DataProvider\SearchResult" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> + <arguments> + <argument name="mainTable" xsi:type="string">url_rewrite</argument> + <argument name="resourceModel" xsi:type="string">Magento\UrlRewrite\Model\ResourceModel\UrlRewrite</argument> + <argument name="identifierName" xsi:type="string">url_rewrite_id</argument> + </arguments> + </virtualType> </config> diff --git a/app/code/Magento/UrlRewrite/etc/module.xml b/app/code/Magento/UrlRewrite/etc/module.xml index eb314b71bc377..310497892747e 100644 --- a/app/code/Magento/UrlRewrite/etc/module.xml +++ b/app/code/Magento/UrlRewrite/etc/module.xml @@ -6,6 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_UrlRewrite" > - </module> + <module name="Magento_UrlRewrite"/> </config> diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml b/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml index 012409a8b6aca..e495f714ee78c 100644 --- a/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml +++ b/app/code/Magento/UrlRewrite/view/adminhtml/layout/adminhtml_url_rewrite_index.xml @@ -8,90 +8,7 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> - <block class="Magento\UrlRewrite\Block\GridContainer" name="adminhtml.block.url_rewrite.grid.container"> - <block class="Magento\Backend\Block\Widget\Grid" name="adminhtml.block.url_rewrite.grid" as="grid"> - <arguments> - <argument name="id" xsi:type="string">urlrewriteGrid</argument> - <argument name="dataSource" xsi:type="object" shared="false">Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection</argument> - <argument name="default_sort" xsi:type="string">url_rewrite_id</argument> - <!-- Add below argument to save session parameter in URL rewrite grid --> - <argument name="save_parameters_in_session" xsi:type="string">1</argument> - </arguments> - <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" as="grid.columnSet" name="adminhtml.url_rewrite.grid.columnSet"> - <arguments> - <argument name="rowUrl" xsi:type="array"> - <item name="path" xsi:type="string">adminhtml/*/edit</item> - <item name="extraParamsTemplate" xsi:type="array"> - <item name="id" xsi:type="string">getId</item> - </item> - </argument> - </arguments> - <block class="Magento\Backend\Block\Widget\Grid\Column" name="adminhtml.url_rewrite.grid.columnSet.url_rewrite_id" as="url_rewrite_id"> - <arguments> - <argument name="header" xsi:type="string" translate="true">ID</argument> - <argument name="type" xsi:type="string">text</argument> - <argument name="id" xsi:type="string">url_rewrite_id</argument> - <argument name="index" xsi:type="string">url_rewrite_id</argument> - <argument name="column_css_class" xsi:type="string">col-id</argument> - <argument name="header_css_class" xsi:type="string">col-id</argument> - </arguments> - </block> - <block class="Magento\Backend\Block\Widget\Grid\Column\Multistore" name="adminhtml.url_rewrite.grid.columnSet.store_id" as="store_id"> - <arguments> - <argument name="header" xsi:type="string" translate="true">Store View</argument> - <argument name="type" xsi:type="string">store</argument> - <argument name="id" xsi:type="string">store_id</argument> - <argument name="index" xsi:type="string">store_id</argument> - <argument name="store_view" xsi:type="string">true</argument> - </arguments> - </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" name="adminhtml.url_rewrite.grid.columnSet.request_path" as="request_path"> - <arguments> - <argument name="header" xsi:type="string" translate="true">Request Path</argument> - <argument name="type" xsi:type="string">text</argument> - <argument name="id" xsi:type="string">request_path</argument> - <argument name="index" xsi:type="string">request_path</argument> - </arguments> - </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" name="adminhtml.url_rewrite.grid.columnSet.target_path" as="target_path"> - <arguments> - <argument name="header" xsi:type="string" translate="true">Target Path</argument> - <argument name="type" xsi:type="string">text</argument> - <argument name="id" xsi:type="string">target_path</argument> - <argument name="index" xsi:type="string">target_path</argument> - </arguments> - </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" name="adminhtml.url_rewrite.grid.columnSet.redirect_type" as="redirect_type"> - <arguments> - <argument name="header" xsi:type="string" translate="true">Redirect Type</argument> - <argument name="type" xsi:type="string">options</argument> - <argument name="id" xsi:type="string">redirect_type</argument> - <argument name="index" xsi:type="string">redirect_type</argument> - <argument name="options" xsi:type="options" model="Magento\UrlRewrite\Model\OptionProvider"/> - </arguments> - </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" name="adminhtml.url_rewrite.grid.columnSet.actions" as="actions"> - <arguments> - <argument name="header" xsi:type="string" translate="true">Action</argument> - <argument name="sortable" xsi:type="string">0</argument> - <argument name="filter" xsi:type="string">0</argument> - <argument name="type" xsi:type="string">action</argument> - <argument name="id" xsi:type="string">actions</argument> - <argument name="index" xsi:type="string">url_rewrite_id</argument> - <argument name="actions" xsi:type="array"> - <item name="view_action" xsi:type="array"> - <item name="caption" xsi:type="string" translate="true">Edit</item> - <item name="url" xsi:type="array"> - <item name="base" xsi:type="string">adminhtml/*/edit</item> - </item> - <item name="field" xsi:type="string">id</item> - </item> - </argument> - </arguments> - </block> - </block> - </block> - </block> + <uiComponent name="url_rewrite_listing"/> </referenceContainer> </body> </page> diff --git a/app/code/Magento/UrlRewrite/view/adminhtml/ui_component/url_rewrite_listing.xml b/app/code/Magento/UrlRewrite/view/adminhtml/ui_component/url_rewrite_listing.xml new file mode 100644 index 0000000000000..39400f1092cbb --- /dev/null +++ b/app/code/Magento/UrlRewrite/view/adminhtml/ui_component/url_rewrite_listing.xml @@ -0,0 +1,158 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="provider" xsi:type="string">url_rewrite_listing.url_rewrite_listing_data_source</item> + </item> + </argument> + <settings> + <buttons> + <button name="add"> + <url path="*/*/edit"/> + <class>primary</class> + <label translate="true">Add URL Rewrite</label> + </button> + </buttons> + <spinner>url_rewrite_listing_columns</spinner> + <deps> + <dep>url_rewrite_listing.url_rewrite_listing_data_source</dep> + </deps> + </settings> + <dataSource name="url_rewrite_listing_data_source" component="Magento_Ui/js/grid/provider"> + <settings> + <storageConfig> + <param name="indexField" xsi:type="string">url_rewrite_id</param> + </storageConfig> + <updateUrl path="mui/index/render"/> + </settings> + <aclResource>Magento_UrlRewrite::urlrewrite</aclResource> + <dataProvider class="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider" + name="url_rewrite_listing_data_source"> + <settings> + <requestFieldName>id</requestFieldName> + <primaryFieldName>url_rewrite_id</primaryFieldName> + </settings> + </dataProvider> + </dataSource> + <listingToolbar name="listing_top"> + <settings> + <sticky>true</sticky> + </settings> + <bookmark name="bookmarks"/> + <columnsControls name="columns_controls"/> + <filters name="listing_filters"> + <filterSelect name="store_id" provider="${ $.parentName }"> + <settings> + <options class="Magento\Store\Ui\Component\Listing\Column\Store\Options"/> + <caption translate="true">All Store Views</caption> + <label translate="true">Store View</label> + <dataScope>store_id</dataScope> + </settings> + </filterSelect> + </filters> + <massaction name="listing_massaction"> + <action name="delete"> + <settings> + <confirm> + <message translate="true">Are you sure you want to delete selected items?</message> + <title translate="true">Delete items + + + delete + + + + + + + + + + + + false + + url_rewrite_id + true + url_rewrite_listing.url_rewrite_listing.url_rewrite_listing_columns.ids + + + + url_rewrite_listing.url_rewrite_listing.url_rewrite_listing_columns_editor + startEdit + + ${ $.$data.rowIndex } + true + + + + + + + url_rewrite_id + + + + + textRange + + desc + + + + + + ui/grid/cells/html + false + + + + + text + + + + true + + text + + + + + + text + + + + + + + select + + select + + select + + + + + + + id + adminhtml/url_rewrite/edit + adminhtml/url_rewrite/delete + + + + url_rewrite_id + + + + diff --git a/app/code/Magento/User/Block/Role/Tab/Edit.php b/app/code/Magento/User/Block/Role/Tab/Edit.php index 5fe6a1b2a2e88..5ba3facfc2d45 100644 --- a/app/code/Magento/User/Block/Role/Tab/Edit.php +++ b/app/code/Magento/User/Block/Role/Tab/Edit.php @@ -63,10 +63,12 @@ class Edit extends \Magento\Backend\Block\Widget\Form implements \Magento\Backen protected $coreRegistry = null; /** + * Constructor + * * @param \Magento\Backend\Block\Template\Context $context + * @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever * @param \Magento\Framework\Acl\RootResource $rootResource * @param \Magento\Authorization\Model\ResourceModel\Rules\CollectionFactory $rulesCollectionFactory - * @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever * @param \Magento\Framework\Acl\AclResource\ProviderInterface $aclResourceProvider * @param \Magento\Integration\Helper\Data $integrationData * @param array $data @@ -222,6 +224,6 @@ function ($node) { } ); $configResource = reset($configResource); - return isset($configResource['children']) ? $configResource['children'] : []; + return $configResource['children'] ?? []; } } diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminBulkOperationsLogIsNotAccessibleForAdminUserWithLimitedAccessTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminBulkOperationsLogIsNotAccessibleForAdminUserWithLimitedAccessTest.xml index 4aa9e7b7fb4cd..e0db8d8b25b96 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminBulkOperationsLogIsNotAccessibleForAdminUserWithLimitedAccessTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminBulkOperationsLogIsNotAccessibleForAdminUserWithLimitedAccessTest.xml @@ -35,7 +35,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -63,9 +63,9 @@ - + - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminCreateActiveUserEntityTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminCreateActiveUserEntityTest.xml index 753ab02f84053..218be4e282b4a 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminCreateActiveUserEntityTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminCreateActiveUserEntityTest.xml @@ -33,7 +33,7 @@ - + @@ -44,6 +44,6 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminCreateInactiveUserEntityTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminCreateInactiveUserEntityTest.xml index d0fdd72ebbdcc..d52cafa13b7b8 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminCreateInactiveUserEntityTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminCreateInactiveUserEntityTest.xml @@ -38,7 +38,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminLockAdminUserEntityTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminLockAdminUserEntityTest.xml index 3bd55a454c3b0..c367bddc8d999 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminLockAdminUserEntityTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminLockAdminUserEntityTest.xml @@ -28,7 +28,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminSystemAllUsersNavigateMenuTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminSystemAllUsersNavigateMenuTest.xml index b899320403d71..57e2ab0faccf6 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminSystemAllUsersNavigateMenuTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminSystemAllUsersNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminSystemLockedUsersNavigateMenuTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminSystemLockedUsersNavigateMenuTest.xml index aea46f3273157..963af44ac3bc0 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminSystemLockedUsersNavigateMenuTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminSystemLockedUsersNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminSystemManageEncryptionKeyNavigateMenuTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminSystemManageEncryptionKeyNavigateMenuTest.xml index f8013a54058c3..d6a4318c7d7be 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminSystemManageEncryptionKeyNavigateMenuTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminSystemManageEncryptionKeyNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminSystemUserRolesNavigateMenuTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminSystemUserRolesNavigateMenuTest.xml index c4052a7f4219c..ef9cb5ebfa5fe 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminSystemUserRolesNavigateMenuTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminSystemUserRolesNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/User/Test/Mftf/Test/AdminUpdateUserTest.xml b/app/code/Magento/User/Test/Mftf/Test/AdminUpdateUserTest.xml index dfadee8ee6807..cfc6016b91906 100644 --- a/app/code/Magento/User/Test/Mftf/Test/AdminUpdateUserTest.xml +++ b/app/code/Magento/User/Test/Mftf/Test/AdminUpdateUserTest.xml @@ -39,7 +39,7 @@ - + @@ -49,7 +49,7 @@ - + @@ -68,7 +68,7 @@ - + diff --git a/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php index cc29c5cffadf1..1f7b149ca07de 100644 --- a/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php @@ -205,7 +205,7 @@ public function scopeConfigGetValue($path) 'carriers/usps/mode' => 0, ]; - return isset($pathMap[$path]) ? $pathMap[$path] : null; + return $pathMap[$path] ?? null; } /** diff --git a/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml index 3185640e3783a..ee7368a44616d 100644 --- a/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml +++ b/app/code/Magento/Variable/Test/Mftf/Test/AdminCreateCustomVariableEntityTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Variable/Test/Mftf/Test/AdminSystemCustomVariablesNavigateMenuTest.xml b/app/code/Magento/Variable/Test/Mftf/Test/AdminSystemCustomVariablesNavigateMenuTest.xml index 74446cf601348..c5d85907d15fc 100644 --- a/app/code/Magento/Variable/Test/Mftf/Test/AdminSystemCustomVariablesNavigateMenuTest.xml +++ b/app/code/Magento/Variable/Test/Mftf/Test/AdminSystemCustomVariablesNavigateMenuTest.xml @@ -23,7 +23,7 @@ - + diff --git a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultAttributesLoadTest.php b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultAttributesLoadTest.php new file mode 100644 index 0000000000000..5a945c5462979 --- /dev/null +++ b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultAttributesLoadTest.php @@ -0,0 +1,134 @@ +paymentMock = $this->getMockBuilder(OrderPaymentInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getEntityId', 'setExtensionAttributes']) + ->getMockForAbstractClass(); + $this->paymentExtensionMock = $this->getMockBuilder(OrderPaymentExtensionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getVaultPaymentToken', 'setVaultPaymentToken']) + ->getMockForAbstractClass(); + + $this->paymentExtensionFactoryMock = $this->createMock(OrderPaymentExtensionFactory::class); + $this->paymentTokenManagementMock = $this->getMockBuilder(PaymentTokenManagementInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getByPaymentId']) + ->getMockForAbstractClass(); + + $this->plugin = (new ObjectManagerHelper($this))->getObject( + PaymentVaultAttributesLoad::class, + [ + 'paymentExtensionFactory' => $this->paymentExtensionFactoryMock, + 'paymentTokenManagement' => $this->paymentTokenManagementMock + ] + ); + } + + /** + * Test case when paymentExtension param was not provided. + */ + public function testAfterGetExtensionAttributesCallsFactoryIfPaymentExtensionIsNull(): void + { + $this->paymentExtensionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->paymentExtensionMock); + + $this->assertSame( + $this->paymentExtensionMock, + $this->plugin->afterGetExtensionAttributes($this->paymentMock, null) + ); + } + + /** + * Test case when payment token was already set. + */ + public function testAfterGetExtensionAttributesWhenPaymentTokenIsNotNull(): void + { + $this->paymentExtensionMock->expects($this->once()) + ->method('getVaultPaymentToken') + ->willReturn($this->createMock(PaymentTokenInterface::class)); + $this->paymentTokenManagementMock->expects($this->never())->method('getByPaymentId'); + $this->paymentMock->expects($this->never())->method('setExtensionAttributes'); + $this->assertSame( + $this->paymentExtensionMock, + $this->plugin->afterGetExtensionAttributes($this->paymentMock, $this->paymentExtensionMock) + ); + } + + /** + * Test case when payment token is null and extension attributes must be set. + */ + public function testAfterGetExtensionAttributesWhenPaymentTokenIsNull(): void + { + $this->paymentExtensionMock->expects($this->once())->method('getVaultPaymentToken')->willReturn(null); + + $paymentTokenMock = $this->createMock(PaymentTokenInterface::class); + $this->paymentTokenManagementMock->expects($this->once()) + ->method('getByPaymentId') + ->willReturn($paymentTokenMock); + $this->paymentExtensionMock->expects($this->once()) + ->method('setVaultPaymentToken') + ->with($paymentTokenMock); + $this->paymentMock->expects($this->once()) + ->method('setExtensionAttributes') + ->with($this->paymentExtensionMock); + + $this->assertSame( + $this->paymentExtensionMock, + $this->plugin->afterGetExtensionAttributes($this->paymentMock, $this->paymentExtensionMock) + ); + } +} diff --git a/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxWithWeeeAttributeActionGroup.xml b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxWithWeeeAttributeActionGroup.xml new file mode 100644 index 0000000000000..ff3f6eb91e04a --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemExcludingTaxWithWeeeAttributeActionGroup.xml @@ -0,0 +1,25 @@ + + + + + + + Validates that the provided product price, subtotal, weee attribute value excluding tax are present and correct in the Shopping Cart. + + + + + + + + + + + + diff --git a/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemWithWeeeAttributeActionGroup.xml b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemWithWeeeAttributeActionGroup.xml new file mode 100644 index 0000000000000..6819afa9a0ad2 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCartItemWithWeeeAttributeActionGroup.xml @@ -0,0 +1,25 @@ + + + + + + + Validates that the provided Product details (Name and Price), Product Quantity, Weee Attribute data are present and correct in the Shopping Cart. + + + + + + + + + + + + diff --git a/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountFPTActionGroup.xml b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountFPTActionGroup.xml new file mode 100644 index 0000000000000..794484b280151 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountFPTActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + EXTENDS: AssertStorefrontCheckoutCartTaxAmountActionGroup. Add check FPT tax summary in Summary section of shopping cart on storefront + + + + + + + + diff --git a/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxWithWeeeAttributeActionGroup.xml b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxWithWeeeAttributeActionGroup.xml new file mode 100644 index 0000000000000..24b25420c1bd6 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryItemsExcludingAndIncludingTaxWithWeeeAttributeActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Goes to the Storefront Shopping Cart page. Validates that the provided Subtotal/Total excluding and including tax, weee attribute total are present and correct. + + + + + + + + diff --git a/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithWeeeEnabledActionGroup.xml b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithWeeeEnabledActionGroup.xml new file mode 100644 index 0000000000000..259afa53f5c32 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithWeeeEnabledActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Validates that the provided Subtotal/Total, Weee total are present and correct. + + + + + + + + diff --git a/app/code/Magento/Weee/Test/Mftf/Data/WeeeConfigData.xml b/app/code/Magento/Weee/Test/Mftf/Data/WeeeConfigData.xml index e44c1bb51e41b..5d55728606a52 100644 --- a/app/code/Magento/Weee/Test/Mftf/Data/WeeeConfigData.xml +++ b/app/code/Magento/Weee/Test/Mftf/Data/WeeeConfigData.xml @@ -22,4 +22,18 @@ 0 + + + ApplyVat + + + 1 + + + + DisableVat + + + 0 + diff --git a/app/code/Magento/Weee/Test/Mftf/Metadata/weee_config-meta.xml b/app/code/Magento/Weee/Test/Mftf/Metadata/weee_config-meta.xml index 56153067658d2..a7009d32eee20 100644 --- a/app/code/Magento/Weee/Test/Mftf/Metadata/weee_config-meta.xml +++ b/app/code/Magento/Weee/Test/Mftf/Metadata/weee_config-meta.xml @@ -14,6 +14,9 @@ string + + string + @@ -27,6 +30,11 @@ integer + + + integer + + diff --git a/app/code/Magento/Weee/Test/Mftf/Page/CheckoutCartPage.xml b/app/code/Magento/Weee/Test/Mftf/Page/CheckoutCartPage.xml new file mode 100644 index 0000000000000..424db8eee8c45 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/Page/CheckoutCartPage.xml @@ -0,0 +1,14 @@ + + + + + +
+ + diff --git a/app/code/Magento/Weee/Test/Mftf/Section/AdminProductAddFPTValueSection.xml b/app/code/Magento/Weee/Test/Mftf/Section/AdminProductAddFPTValueSection.xml index 8a9e9ff6a7169..13383c9df121f 100644 --- a/app/code/Magento/Weee/Test/Mftf/Section/AdminProductAddFPTValueSection.xml +++ b/app/code/Magento/Weee/Test/Mftf/Section/AdminProductAddFPTValueSection.xml @@ -11,10 +11,10 @@
- - - - + + + +
diff --git a/app/code/Magento/Weee/Test/Mftf/Section/StorefrontCheckoutCartItemWeeeSection.xml b/app/code/Magento/Weee/Test/Mftf/Section/StorefrontCheckoutCartItemWeeeSection.xml new file mode 100644 index 0000000000000..8c656af42cbf5 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/Section/StorefrontCheckoutCartItemWeeeSection.xml @@ -0,0 +1,17 @@ + + + + +
+ + + + +
+
diff --git a/app/code/Magento/Weee/Test/Mftf/Test/AdminFixedTaxValSavedForSpecificWebsiteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/AdminFixedTaxValSavedForSpecificWebsiteTest.xml index 6cbdbe0db267d..b929fd3d304c0 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/AdminFixedTaxValSavedForSpecificWebsiteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/AdminFixedTaxValSavedForSpecificWebsiteTest.xml @@ -66,7 +66,7 @@ - + diff --git a/app/code/Magento/Weee/Test/Mftf/Test/AdminRemoveProductWeeeAttributeOptionTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/AdminRemoveProductWeeeAttributeOptionTest.xml index 6164f037048ba..d3f39e9aee664 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/AdminRemoveProductWeeeAttributeOptionTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/AdminRemoveProductWeeeAttributeOptionTest.xml @@ -41,7 +41,7 @@ - + diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml similarity index 50% rename from app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml rename to app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml index d81ea25de87a4..befce13ef036b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml @@ -8,17 +8,20 @@ - + <description value="Tax information are updating/recalculating on fly in shopping cart for Customer with default addresses (physical quote)"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-41932"/> + <useCaseId value="MC-294"/> + <testCaseId value="MC-28586"/> <group value="checkout"/> <group value="tax"/> + <group value="weee"/> </annotations> + <before> <!-- Preconditions --> <!-- Tax Rule is created based on default tax rates (Stores>Tax Rule) US-CA-*-Rate 1 = 8.2500 US-NY-*-Rate 1 = 8.3750 --> @@ -33,93 +36,89 @@ <!-- Store>Configuration; Sales>Tax FPT Enable --> <createData entity="WeeeConfigEnable" stepKey="enableFPT"/> <!-- Simple product is created Price = 10; FPT United States/California/10,United States/New York/20 --> - <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> <field key="price">10.00</field> - <requiredEntity createDataKey="createCategory"/> </createData> <!-- Customer is created with default addresses: --> <createData entity="Simple_US_Customer_CA" stepKey="createCustomer"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openProductEditPage"> + <argument name="productId" value="$createSimpleProduct.id$"/> </actionGroup> <actionGroup ref="AdminProductAddFPTValueActionGroup" stepKey="addFPTValue1"> - <argument name="FPTAttributeCode" value="$$createProductFPTAttribute.attribute_code$$"/> + <argument name="FPTAttributeCode" value="$createProductFPTAttribute.attribute_code$"/> <argument name="stateForFPT" value="California"/> <argument name="valueForFPT" value="10"/> </actionGroup> <actionGroup ref="AdminProductAddFPTValueActionGroup" stepKey="addFPTValue2"> - <argument name="FPTAttributeCode" value="$$createProductFPTAttribute.attribute_code$$"/> + <argument name="FPTAttributeCode" value="$createProductFPTAttribute.attribute_code$"/> <argument name="stateForFPT" value="New York"/> <argument name="valueForFPT" value="20"/> </actionGroup> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> - <waitForPageLoad stepKey="waitForProductIndexPageLoad"/> - <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> + <!-- Delete all catalog price rules that can (and actually do) affect this test--> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </before> + <after> + <!-- Need to logout first because otherwise selenium fail with timeout --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> <deleteData createDataKey="createProductFPTAttribute" stepKey="deleteProductFPTAttribute"/> <createData entity="DefaultTaxConfig" stepKey="defaultTaxConfiguration"/> <createData entity="WeeeConfigDisable" stepKey="disableFPT"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="logout"/> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </after> + <!-- Test Steps --> <!-- Step 1: Go to Storefront as logged in Customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> - <argument name="Customer" value="$$createCustomer$$" /> + <argument name="Customer" value="$createCustomer$" /> </actionGroup> <!-- Step 2: Add simple product to shopping cart --> - <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.name$$)}}" stepKey="amOnSimpleProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($createSimpleProduct.custom_attributes[url_key]$)}}" stepKey="amOnSimpleProductPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> - <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="cartAddSimpleProductToCart"> - <argument name="product" value="$$createSimpleProduct$$"/> - <argument name="productCount" value="1"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="cartAddSimpleProductToCart"> + <argument name="productName" value="$createSimpleProduct.name$"/> </actionGroup> <!-- Step 3: Go to Shopping Cart --> <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> <!-- Step 4: Open Estimate Shipping and Tax section --> - <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingandTax" /> - <seeOptionIsSelected selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_CA.country}}" stepKey="checkCustomerCountry" /> - <seeOptionIsSelected selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_CA.state}}" stepKey="checkCustomerRegion" /> - <grabValueFrom selector="{{CheckoutCartSummarySection.postcode}}" stepKey="grabTextPostCode"/> - <assertEquals message="Customer postcode is invalid" stepKey="checkCustomerPostcode"> - <expectedResult type="string">{{US_Address_CA.postcode}}</expectedResult> - <actualResult type="variable">grabTextPostCode</actualResult> - </assertEquals> - <see selector="{{CheckoutCartSummarySection.amountFPT}}" userInput="$10" stepKey="checkFPTAmountCA" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.83" stepKey="checkTaxAmountCA" /> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary"/> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-CA-*-Rate 1 (8.25%)" stepKey="checkRateCA" /> + <actionGroup ref="AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup" stepKey="checkAddress"> + <argument name="country" value="{{US_Address_CA.country}}"/> + <argument name="state" value="{{US_Address_CA.state}}"/> + <argument name="postcode" value="{{US_Address_CA.postcode}}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountFPTActionGroup" stepKey="checkTaxAmountCA"/> <!-- Step 5: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Switzerland" stepKey="selectSwitzerlandCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Aargau" stepKey="selectAargauRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="1234" stepKey="inputPostCode"/> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToSwitzerland"> + <argument name="country" value="Switzerland"/> + <argument name="state" value="Aargau"/> + <argument name="postcode" value="1234"/> + </actionGroup> <!-- Step 6: Select shipping rate again(it need for get new totals request - performance reason) --> - <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectflatRateShippingMethodShippingMethod"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary2" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmount" /> + <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethod"/> + <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary" /> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmountZero" /> <dontSeeElement selector="{{CheckoutCartSummarySection.amountFPT}}" stepKey="checkFPTIsNotDisplayed" /> <!-- Step 7: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUnitedStatesCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="New York" stepKey="selectNewYorkRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="12345" stepKey="inputPostCode2"/> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="New York"/> + <argument name="postcode" value="12345"/> + </actionGroup> <!-- Step 8: Select shipping rate again(it need for get new totals request - performance reason) --> - <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectflatRateShippingMethodShippingMethod2"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary3" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary3"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.84" stepKey="checkTaxAmountNY" /> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-NY-*-Rate 1 (8.375%)" stepKey="checkRateNY" /> - <see selector="{{CheckoutCartSummarySection.amountFPT}}" userInput="$20" stepKey="checkFPTAmountNY" /> + <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethodAgain"/> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountFPTActionGroup" stepKey="checkTaxAmountNY"> + <argument name="FPTAmount" value="$20"/> + <argument name="taxAmount" value="$0.84"/> + <argument name="rate" value="US-NY-*-Rate 1 (8.375%)"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml similarity index 52% rename from app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml rename to app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml index c62fc59a52e68..8abdbede98922 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml @@ -8,17 +8,20 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest"> + <test name="StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest"> <annotations> <features value="Tax"/> <stories value="Shopping cart taxes"/> <title value="Tax information are updating/recalculating on fly in shopping cart for Customer with default addresses (virtual quote)"/> <description value="Tax information are updating/recalculating on fly in shopping cart for Customer with default addresses (virtual quote)"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-41933"/> + <useCaseId value="MC-294"/> + <testCaseId value="MC-28585"/> <group value="checkout"/> <group value="tax"/> + <group value="weee"/> </annotations> + <before> <!-- Preconditions --> <!-- Tax Rule is created based on default tax rates (Stores>Tax Rule) US-CA-*-Rate 1 = 8.2500 US-NY-*-Rate 1 = 8.3750 --> @@ -36,54 +39,65 @@ </createData> <!-- Customer is created with default addresses: --> <createData entity="Simple_US_Customer_NY" stepKey="createCustomer"/> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Delete all catalog price rules that can (and actually do) affect this test--> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </before> + <after> + <!-- Need to logout first because otherwise selenium fail with timeout --> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> <deleteData createDataKey="createProductFPTAttribute" stepKey="deleteProductFPTAttribute"/> <createData entity="DefaultTaxConfig" stepKey="defaultTaxConfiguration"/> <deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </after> + <!-- Test Steps --> <!-- Step 1: Go to Storefront as logged in Customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> - <argument name="Customer" value="$$createCustomer$$" /> + <argument name="Customer" value="$createCustomer$" /> </actionGroup> <!-- Step 2: Add virtual product to shopping cart --> - <amOnPage url="{{StorefrontProductPage.url($$createVirtualProduct.name$$)}}" stepKey="amOnStorefrontVirtualProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($createVirtualProduct.custom_attributes[url_key]$)}}" stepKey="amOnStorefrontVirtualProductPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> - <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="cartAddVirtualProductToCart"> - <argument name="product" value="$$createVirtualProduct$$"/> - <argument name="productCount" value="1"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="cartAddVirtualProductToCart"> + <argument name="productName" value="$createVirtualProduct.name$"/> </actionGroup> <!-- Step 3: Go to Shopping Cart --> <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> <!-- Step 4: Open Estimate Shipping and Tax section --> - <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingandTax" /> - <seeOptionIsSelected selector="{{CheckoutCartSummarySection.country}}" userInput="{{US_Address_NY.country}}" stepKey="checkCustomerCountry" /> - <seeOptionIsSelected selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="{{US_Address_NY.state}}" stepKey="checkCustomerRegion" /> - <grabValueFrom selector="{{CheckoutCartSummarySection.postcode}}" stepKey="grabTextPostCode"/> - <assertEquals message="Customer postcode is invalid" stepKey="checkCustomerPostcode"> - <expectedResult type="string">{{US_Address_NY.postcode}}</expectedResult> - <actualResult type="variable">grabTextPostCode</actualResult> - </assertEquals> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="expandTaxSummary"/> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-NY-*-Rate 1 (8.375%)" stepKey="checkRateNY" /> + <actionGroup ref="AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup" stepKey="checkAddress"> + <argument name="country" value="{{US_Address_NY.country}}"/> + <argument name="state" value="{{US_Address_NY.state}}"/> + <argument name="postcode" value="{{US_Address_NY.postcode}}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountActionGroup" stepKey="checkTaxAmountNY"> + <argument name="taxAmount" value="$3.35"/> + <argument name="rate" value="US-NY-*-Rate 1 (8.375%)"/> + </actionGroup> <!-- Step 5: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Switzerland" stepKey="selectSwitzerlandCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Aargau" stepKey="selectAargauRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="1234" stepKey="inputPostCode"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary2" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmount" /> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToSwitzerland"> + <argument name="country" value="Switzerland"/> + <argument name="state" value="Aargau"/> + <argument name="postcode" value="1234"/> + </actionGroup> + <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary" /> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmountZero" /> <!-- Step 6: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUnitedStatesCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="California" stepKey="selectCaliforniaRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="90230" stepKey="inputPostCode2"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary3" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary2"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$3.30" stepKey="checkTaxAmount2" /> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-CA-*-Rate 1 (8.25%)" stepKey="checkRateCA" /> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="California"/> + <argument name="postcode" value="90230"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountActionGroup" stepKey="checkTaxAmountCA"> + <argument name="taxAmount" value="$3.30"/> + <argument name="rate" value="US-CA-*-Rate 1 (8.25%)"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml similarity index 50% rename from app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml rename to app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml index e8c2f1a66f0c3..d4e5ed74be9a3 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml @@ -8,17 +8,20 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest"> + <test name="StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest"> <annotations> <features value="Tax"/> <stories value="Shopping cart taxes"/> <title value="Tax information are updating/recalculating on fly in shopping cart for Guest (physical quote)"/> <description value="Tax information are updating/recalculating on fly in shopping cart for Guest (physical quote)"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-41930"/> + <useCaseId value="MC-294"/> + <testCaseId value="MC-28592"/> <group value="checkout"/> <group value="tax"/> + <group value="weee"/> </annotations> + <before> <!-- Preconditions --> <!-- Tax Rule is created based on default tax rates (Stores>Tax Rule) US-CA-*-Rate 1 = 8.2500 US-NY-*-Rate 1 = 8.3750 --> @@ -33,83 +36,81 @@ <!-- Store>Configuration; Sales>Tax FPT Enable --> <createData entity="WeeeConfigEnable" stepKey="enableFPT"/> <!-- Simple product is created Price = 10; FPT United States/California/10,United States/New York/20 --> - <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> <field key="price">10.00</field> - <requiredEntity createDataKey="createCategory"/> </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="openEditProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openProductEditPage"> + <argument name="productId" value="$createSimpleProduct.id$"/> </actionGroup> <actionGroup ref="AdminProductAddFPTValueActionGroup" stepKey="addFPTValue1"> - <argument name="FPTAttributeCode" value="$$createProductFPTAttribute.attribute_code$$"/> + <argument name="FPTAttributeCode" value="$createProductFPTAttribute.attribute_code$"/> <argument name="stateForFPT" value="California"/> <argument name="valueForFPT" value="10"/> </actionGroup> <actionGroup ref="AdminProductAddFPTValueActionGroup" stepKey="addFPTValue2"> - <argument name="FPTAttributeCode" value="$$createProductFPTAttribute.attribute_code$$"/> + <argument name="FPTAttributeCode" value="$createProductFPTAttribute.attribute_code$"/> <argument name="stateForFPT" value="New York"/> <argument name="valueForFPT" value="20"/> </actionGroup> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> - <waitForPageLoad stepKey="waitForProductIndexPageLoad"/> - <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridToDefaultKeywordSearch"/> + <!-- Delete all catalog price rules that can (and actually do) affect this test--> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </before> + <after> <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> <deleteData createDataKey="createProductFPTAttribute" stepKey="deleteProductFPTAttribute"/> <createData entity="DefaultTaxConfig" stepKey="defaultTaxConfiguration"/> <createData entity="WeeeConfigDisable" stepKey="disableFPT"/> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> </after> + <!-- Test Steps --> <!-- Step 1: Go to Storefront as Guest --> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Step 2: Add simple product to shopping cart --> - <amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.name$$)}}" stepKey="amOnSimpleProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($createSimpleProduct.custom_attributes[url_key]$)}}" stepKey="amOnSimpleProductPage"/> <waitForPageLoad stepKey="waitForPageLoad2"/> - <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="cartAddSimpleProductToCart"> - <argument name="product" value="$$createSimpleProduct$$"/> - <argument name="productCount" value="1"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="cartAddSimpleProductToCart"> + <argument name="productName" value="$createSimpleProduct.name$"/> </actionGroup> <!-- Step 3: Go to Shopping Cart --> <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> <!-- Step 4: Open Estimate Shipping and Tax section --> - <conditionalClick selector="{{CheckoutCartSummarySection.estimateShippingAndTax}}" dependentSelector="{{CheckoutCartSummarySection.country}}" visible="false" stepKey="expandEstimateShippingandTax" /> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUSCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="California" stepKey="selectCaliforniaRegion"/> - <see selector="{{CheckoutCartSummarySection.amountFPT}}" userInput="$10" stepKey="checkFPTAmountCA" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.83" stepKey="checkTaxAmountCA" /> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary"/> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-CA-*-Rate 1 (8.25%)" stepKey="checkRateCA" /> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxInitialAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="California"/> + <argument name="postcode" value="*"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountFPTActionGroup" stepKey="checkTaxAmountCA"/> <!-- Step 5: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Switzerland" stepKey="selectSwitzerlandCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Aargau" stepKey="selectAargauRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="1234" stepKey="inputPostCode"/> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToSwitzerland"> + <argument name="country" value="Switzerland"/> + <argument name="state" value="Aargau"/> + <argument name="postcode" value="1234"/> + </actionGroup> <!-- Step 6: Select shipping rate again(it need for get new totals request - performance reason) --> - <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectflatRateShippingMethodShippingMethod"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary2" /> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmount" /> + <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethod"/> + <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary" /> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmountZero" /> <dontSeeElement selector="{{CheckoutCartSummarySection.amountFPT}}" stepKey="checkFPTIsNotDisplayed" /> <!-- Step 7: Change Data --> - <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectUnitedStatesCountry"/> - <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="New York" stepKey="selectNewYorkRegion"/> - <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="12345" stepKey="inputPostCode2"/> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="New York"/> + <argument name="postcode" value="12345"/> + </actionGroup> <!-- Step 8: Select shipping rate again(it need for get new totals request - performance reason) --> - <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectflatRateShippingMethodShippingMethod2"/> - <scrollTo selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="scrollToTaxSummary3" /> - <click selector="{{CheckoutCartSummarySection.taxSummary}}" stepKey="taxSummary2"/> - <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.84" stepKey="checkTaxAmountNY" /> - <see selector="{{CheckoutCartSummarySection.rate}}" userInput="US-NY-*-Rate 1 (8.375%)" stepKey="checkRateNY" /> - <see selector="{{CheckoutCartSummarySection.amountFPT}}" userInput="$20" stepKey="checkFPTAmountNY" /> + <click selector="{{CheckoutCartSummarySection.flatRateShippingMethod}}" stepKey="selectFlatRateShippingMethodAgain"/> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountFPTActionGroup" stepKey="checkTaxAmountNY"> + <argument name="FPTAmount" value="$20"/> + <argument name="taxAmount" value="$0.84"/> + <argument name="rate" value="US-NY-*-Rate 1 (8.375%)"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml new file mode 100644 index 0000000000000..0fc4af813c5a1 --- /dev/null +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml @@ -0,0 +1,96 @@ +<?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="StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest"> + <annotations> + <features value="Tax"/> + <stories value="Shopping cart taxes"/> + <title value="Tax information are updating/recalculating on fly in shopping cart for Guest (virtual quote)"/> + <description value="Tax information are updating/recalculating on fly in shopping cart for Guest (virtual quote)"/> + <severity value="CRITICAL"/> + <useCaseId value="MC-294"/> + <testCaseId value="MC-26557"/> + <group value="checkout"/> + <group value="tax"/> + <group value="weee"/> + </annotations> + + <before> + <!-- Preconditions --> + <!-- Tax Rule is created based on default tax rates (Stores>Tax Rule) US-CA-*-Rate 1 = 8.2500 US-NY-*-Rate 1 = 8.3750 --> + <createData entity="SimpleTaxRule" stepKey="createTaxRule"/> + <!-- Fixed Product Tax attribute is created and added to default attribute set --> + <createData entity="productFPTAttribute" stepKey="createProductFPTAttribute"/> + <createData entity="AddToDefaultSet" stepKey="addFPTToAttributeSet"> + <requiredEntity createDataKey="createProductFPTAttribute"/> + </createData> + <!-- Tax configuration (Store>Configuration; Sales>Tax) --> + <createData entity="Tax_Config_CA" stepKey="taxConfigurationCA"/> + <!-- Virtual product is created: Price = 10 --> + <createData entity="VirtualProduct" stepKey="createVirtualProduct"> + <field key="price">40.00</field> + </createData> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Delete all catalog price rules that can (and actually do) affect this test--> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> + </before> + + <after> + <deleteData createDataKey="createTaxRule" stepKey="deleteTaxRule"/> + <deleteData createDataKey="createProductFPTAttribute" stepKey="deleteProductFPTAttribute"/> + <createData entity="DefaultTaxConfig" stepKey="defaultTaxConfiguration"/> + <deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProduct"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexBrokenIndices"/> + </after> + + <!-- Test Steps --> + <!-- Step 1: Go to Storefront as Guest --> + <!-- Step 2: Add virtual product to shopping cart --> + <amOnPage url="{{StorefrontProductPage.url($createVirtualProduct.custom_attributes[url_key]$)}}" stepKey="amOnStorefrontVirtualProductPage"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="cartAddVirtualProductToCart"> + <argument name="productName" value="$createVirtualProduct.name$"/> + </actionGroup> + <!-- Step 3: Go to Shopping Cart --> + <actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/> + <!-- Step 4: Open Estimate Shipping and Tax section --> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxInitialAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="California"/> + <argument name="postcode" value="*"/> + </actionGroup> + + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountActionGroup" stepKey="checkTaxAmountCA"> + <argument name="taxAmount" value="$3.30"/> + <argument name="rate" value="US-CA-*-Rate 1 (8.25%)"/> + </actionGroup> + <!-- Step 5: Change Data --> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToSwitzerland"> + <argument name="country" value="Switzerland"/> + <argument name="state" value="Aargau"/> + <argument name="postcode" value="1234"/> + </actionGroup> + <scrollTo selector="{{CheckoutCartSummarySection.taxAmount}}" stepKey="scrollToTaxSummary" /> + <see selector="{{CheckoutCartSummarySection.taxAmount}}" userInput="$0.00" stepKey="checkTaxAmountZero" /> + <!-- Step 6: Change Data --> + <actionGroup ref="StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup" stepKey="setEstimateShippingAndTaxAddressToUnitedStates"> + <argument name="country" value="United States"/> + <argument name="state" value="New York"/> + <argument name="postcode" value="12345"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCheckoutCartTaxAmountActionGroup" stepKey="checkTaxAmountNY"> + <argument name="taxAmount" value="$3.35"/> + <argument name="rate" value="US-NY-*-Rate 1 (8.375%)"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Weee/Test/Unit/Observer/UpdateElementTypesObserverTest.php b/app/code/Magento/Weee/Test/Unit/Observer/UpdateElementTypesObserverTest.php new file mode 100644 index 0000000000000..bcdbfe1d6f03f --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Observer/UpdateElementTypesObserverTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Weee\Test\Unit\Observer; + +use Magento\Framework\DataObject; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Reports\Model\Event; +use Magento\Weee\Block\Element\Weee\Tax; +use Magento\Weee\Observer\UpdateElementTypesObserver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for Magento\Weee\Observer\UpdateElementTypesObserver + */ +class UpdateElementTypesObserverTest extends TestCase +{ + /* + * Stub response type + */ + const STUB_RESPONSE_TYPE = []; + + /** + * Testable Object + * + * @var UpdateElementTypesObserver + */ + private $observer; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * @var DataObject|MockObject + */ + private $responseMock; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getResponse']) + ->getMock(); + + $this->responseMock = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->setMethods(['getTypes', 'setTypes']) + ->getMock(); + + $this->observer = $this->objectManager->getObject(UpdateElementTypesObserver::class); + } + + /** + * Test for execute(), covers test case to adding custom element type for attributes form + */ + public function testRemoveProductUrlsFromStorage(): void + { + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getResponse') + ->willReturn($this->responseMock); + + $this->responseMock + ->expects($this->once()) + ->method('getTypes') + ->willReturn(self::STUB_RESPONSE_TYPE); + + $this->responseMock + ->expects($this->once()) + ->method('setTypes') + ->with(['weee' => Tax::class]); + + $this->observer->execute($this->observerMock); + } +} diff --git a/app/code/Magento/Widget/Test/Mftf/Test/AdminContentWidgetsNavigateMenuTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/AdminContentWidgetsNavigateMenuTest.xml index f5af024ec1d51..e62383d57fc93 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/AdminContentWidgetsNavigateMenuTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/AdminContentWidgetsNavigateMenuTest.xml @@ -23,7 +23,7 @@ <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToContentWidgetsPage"> <argument name="menuUiId" value="{{AdminMenuContent.dataUiId}}"/> diff --git a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml index e2fb9cb50f88a..e3e0b957cf550 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml @@ -27,7 +27,7 @@ </before> <after> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Create a CMS page containing the New Products widget --> diff --git a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml index 4407991ff5a93..df9b724783372 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml @@ -6,8 +6,7 @@ */ --> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ProductsListWidgetTest"> <annotations> <features value="Widget"/> @@ -28,7 +27,7 @@ </before> <after> <conditionalClick selector="{{CmsPagesPageActionsSection.clearAllButton}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> </after> @@ -61,8 +60,10 @@ <click selector="{{CmsPagesPageActionsSection.select(_newDefaultCmsPage.title)}}" stepKey="clickSelect" /> <waitForElementVisible selector="{{CmsPagesPageActionsSection.edit(_newDefaultCmsPage.title)}}" stepKey="waitForEditLink" /> <click selector="{{CmsPagesPageActionsSection.preview(_newDefaultCmsPage.title)}}" stepKey="clickEdit" /> + <switchToNextTab stepKey="switchToNextTab"/> <waitForPageLoad stepKey="waitForCMSPage"/> <seeInTitle userInput="{{_newDefaultCmsPage.title}}" stepKey="seePageTitle"/> <see userInput="{{_newDefaultCmsPage.title}}" stepKey="seeProduct"/> + <closeTab stepKey="closeCurrentTab"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php index 87260305a3d0f..53b0044d82f04 100644 --- a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php +++ b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php @@ -9,52 +9,52 @@ class ChooserTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Model\ResourceModel\Category\Collection|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ResourceModel\Category\Collection|\PHPUnit\Framework\MockObject\MockObject */ protected $collection; /** - * @var \Magento\Framework\Data\Tree\Node|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Tree\Node|\PHPUnit\Framework\MockObject\MockObject */ protected $childNode; /** - * @var \Magento\Framework\Data\Tree\Node|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Tree\Node|\PHPUnit\Framework\MockObject\MockObject */ protected $rootNode; /** - * @var \Magento\Catalog\Model\ResourceModel\Category\Tree|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ResourceModel\Category\Tree|\PHPUnit\Framework\MockObject\MockObject */ protected $categoryTree; /** - * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\Store|\PHPUnit\Framework\MockObject\MockObject */ protected $store; /** - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $storeManager; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Escaper|\PHPUnit\Framework\MockObject\MockObject */ protected $escaper; /** - * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $eventManager; /** - * @var \Magento\Backend\Block\Template\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Backend\Block\Template\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; diff --git a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Chooser/AbstractContainerTest.php b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Chooser/AbstractContainerTest.php index c84e56d5869bb..ab1c73596201c 100644 --- a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Chooser/AbstractContainerTest.php +++ b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Chooser/AbstractContainerTest.php @@ -10,47 +10,47 @@ abstract class AbstractContainerTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\Event\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\Manager|\PHPUnit\Framework\MockObject\MockObject */ protected $eventManagerMock; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $scopeConfigMock; /** - * @var \Magento\Backend\Block\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Backend\Block\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $contextMock; /** - * @var \Magento\Theme\Model\ResourceModel\Theme\Collection|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Theme\Model\ResourceModel\Theme\Collection|\PHPUnit\Framework\MockObject\MockObject */ protected $themeCollectionMock; /** - * @var \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $themeCollectionFactoryMock; /** - * @var \Magento\Theme\Model\Theme|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Theme\Model\Theme|\PHPUnit\Framework\MockObject\MockObject */ protected $themeMock; /** - * @var \Magento\Framework\View\Layout\ProcessorFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout\ProcessorFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $layoutProcessorFactoryMock; /** - * @var \Magento\Framework\View\Model\Layout\Merge|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Model\Layout\Merge|\PHPUnit\Framework\MockObject\MockObject */ protected $layoutMergeMock; /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Escaper|\PHPUnit\Framework\MockObject\MockObject */ protected $escaperMock; diff --git a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Tab/PropertiesTest.php b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Tab/PropertiesTest.php index b83be871de34e..471947e15091f 100644 --- a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Tab/PropertiesTest.php +++ b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Instance/Edit/Tab/PropertiesTest.php @@ -8,12 +8,12 @@ class PropertiesTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $widget; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $registry; diff --git a/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php index 5e88a6e356076..5e3600767b302 100644 --- a/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php +++ b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php @@ -9,17 +9,17 @@ class CategoriesTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Math\Random|\PHPUnit\Framework\MockObject\MockObject */ protected $mathRandom; /** - * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout|\PHPUnit\Framework\MockObject\MockObject */ protected $chooser; @@ -29,22 +29,22 @@ class CategoriesTest extends \PHPUnit\Framework\TestCase protected $blockClass = \Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser::class; /** - * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout|\PHPUnit\Framework\MockObject\MockObject */ protected $layout; /** - * @var \Magento\Framework\Controller\Result\Raw|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Raw|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRaw; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactory; /** - * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Backend\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; diff --git a/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/LoadOptionsTest.php b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/LoadOptionsTest.php index e3be77193be01..79f75a1807ce9 100644 --- a/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/LoadOptionsTest.php +++ b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/LoadOptionsTest.php @@ -26,32 +26,32 @@ class LoadOptionsTest extends \PHPUnit\Framework\TestCase private $objectManagerHelper; /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject + * @var Context|\PHPUnit\Framework\MockObject\MockObject */ private $contextMock; /** - * @var ViewInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ViewInterface|\PHPUnit\Framework\MockObject\MockObject */ private $viewMock; /** - * @var ConditionsHelper|\PHPUnit_Framework_MockObject_MockObject + * @var ConditionsHelper|\PHPUnit\Framework\MockObject\MockObject */ private $conditionsHelperMock; /** - * @var ResponseInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */ private $responseMock; /** - * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ private $objectManagerMock; /** - * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ private $requestMock; @@ -110,7 +110,7 @@ public function dtestExecuteWithException() $jsonResult = '{"error":true,"message":"Some error"}'; $errorMessage = 'Some error'; - /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject $jsonDataHelperMock */ + /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit\Framework\MockObject\MockObject $jsonDataHelperMock */ $jsonDataHelperMock = $this->getMockBuilder(\Magento\Framework\Json\Helper\Data::class) ->disableOriginalConstructor() ->getMock(); @@ -163,7 +163,7 @@ public function testExecute() ], ]; - /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject $jsonDataHelperMock */ + /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit\Framework\MockObject\MockObject $jsonDataHelperMock */ $jsonDataHelperMock = $this->getMockBuilder(\Magento\Framework\Json\Helper\Data::class) ->disableOriginalConstructor() ->getMock(); @@ -183,7 +183,7 @@ public function testExecute() ->with(\Magento\Framework\Json\Helper\Data::class) ->willReturn($jsonDataHelperMock); - /** @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit_Framework_MockObject_MockObject $blockMock */ + /** @var \Magento\Framework\View\Element\BlockInterface|\PHPUnit\Framework\MockObject\MockObject $blockMock */ $blockMock = $this->getMockBuilder(\Magento\Framework\View\Element\BlockInterface::class) ->setMethods(['setWidgetType', 'setWidgetValues']) ->getMockForAbstractClass(); @@ -196,7 +196,7 @@ public function testExecute() ->with($resultWidgetArrayParams['values']) ->willReturnSelf(); - /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $layoutMock */ + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit\Framework\MockObject\MockObject $layoutMock */ $layoutMock = $this->getMockForAbstractClass(\Magento\Framework\View\LayoutInterface::class); $layoutMock->expects($this->once()) ->method('getBlock') diff --git a/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php b/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php index f943a5688b56c..e0865432aedb0 100644 --- a/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php +++ b/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php @@ -11,6 +11,8 @@ /** * Class ConditionsTest + * + * PHPUnit test case for \Magento\Widget\Helper\Conditions */ class ConditionsTest extends \PHPUnit\Framework\TestCase { @@ -20,12 +22,12 @@ class ConditionsTest extends \PHPUnit\Framework\TestCase protected $conditions; /** - * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit\Framework\MockObject\MockObject */ private $serializer; /** - * @var Normalizer|\PHPUnit_Framework_MockObject_MockObject + * @var Normalizer|\PHPUnit\Framework\MockObject\MockObject */ private $normalizer; diff --git a/app/code/Magento/Widget/Test/Unit/Model/Config/FileResolverTest.php b/app/code/Magento/Widget/Test/Unit/Model/Config/FileResolverTest.php index 301869a50a713..730a9adfb8b93 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/Config/FileResolverTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/Config/FileResolverTest.php @@ -17,17 +17,17 @@ class FileResolverTest extends \PHPUnit\Framework\TestCase private $object; /** - * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit\Framework\MockObject\MockObject */ private $moduleReader; /** - * @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit\Framework\MockObject\MockObject */ private $factory; /** - * @var \Magento\Framework\Component\DirSearch|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Component\DirSearch|\PHPUnit\Framework\MockObject\MockObject */ private $componentDirSearch; diff --git a/app/code/Magento/Widget/Test/Unit/Model/NamespaceResolverTest.php b/app/code/Magento/Widget/Test/Unit/Model/NamespaceResolverTest.php index 0bf2717a54286..e3b61fe9e0bfc 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/NamespaceResolverTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/NamespaceResolverTest.php @@ -13,7 +13,7 @@ class NamespaceResolverTest extends \PHPUnit\Framework\TestCase protected $namespaceResolver; /** - * @var \Magento\Framework\Module\ModuleListInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Module\ModuleListInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $moduleListMock; diff --git a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/AbstractTestCase.php b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/AbstractTestCase.php index 32c4d72c8bccd..4ccb436ca83f4 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/AbstractTestCase.php +++ b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/AbstractTestCase.php @@ -51,7 +51,7 @@ protected function setUp() * Retrieve resource model instance * * @param \Magento\Framework\DB\Select $select - * @return \PHPUnit_Framework_MockObject_MockObject + * @return \PHPUnit\Framework\MockObject\MockObject */ protected function _getResource(\Magento\Framework\DB\Select $select) { @@ -88,7 +88,7 @@ public function testAddUpdatedDaysBeforeFilter() $collection = $this->_getCollection($select); - /** @var $connection \PHPUnit_Framework_MockObject_MockObject */ + /** @var $connection \PHPUnit\Framework\MockObject\MockObject */ $connection = $collection->getResource()->getConnection(); $connection->expects( $this->any() diff --git a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Link/CollectionTest.php b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Link/CollectionTest.php index 825d2ca50feda..29e35c9524beb 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Link/CollectionTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Link/CollectionTest.php @@ -52,7 +52,7 @@ public function testAddTemporaryFilter($flag) $collection = $this->_getCollection($select); - /** @var $connection \PHPUnit_Framework_MockObject_MockObject */ + /** @var $connection \PHPUnit\Framework\MockObject\MockObject */ $connection = $collection->getResource()->getConnection(); $connection->expects( $this->any() @@ -97,7 +97,7 @@ public function testJoinWithUpdate() $collection = $this->_getCollection($select); - /** @var $resource \PHPUnit_Framework_MockObject_MockObject */ + /** @var $resource \PHPUnit\Framework\MockObject\MockObject */ $resource = $collection->getResource(); $resource->expects( $this->once() diff --git a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Update/CollectionTest.php b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Update/CollectionTest.php index 3467378eaeb9c..2af3dd4476e3f 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Update/CollectionTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Layout/Update/CollectionTest.php @@ -85,7 +85,7 @@ public function testAddNoLinksFilter() $collection = $this->_getCollection($select); - /** @var $connection \PHPUnit_Framework_MockObject_MockObject */ + /** @var $connection \PHPUnit\Framework\MockObject\MockObject */ $connection = $collection->getResource()->getConnection(); $connection->expects( $this->once() diff --git a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Widget/Instance/Options/ThemesTest.php b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Widget/Instance/Options/ThemesTest.php index cc87b98b28ed5..6744227b3d188 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Widget/Instance/Options/ThemesTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/ResourceModel/Widget/Instance/Options/ThemesTest.php @@ -20,12 +20,12 @@ class ThemesTest extends \PHPUnit\Framework\TestCase private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ private $themeCollectionFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ private $themeCollectionMock; diff --git a/app/code/Magento/Widget/Test/Unit/Model/Template/FilterEmulateTest.php b/app/code/Magento/Widget/Test/Unit/Model/Template/FilterEmulateTest.php index f49ee97818618..4be86a25403e3 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/Template/FilterEmulateTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/Template/FilterEmulateTest.php @@ -20,7 +20,7 @@ class FilterEmulateTest extends \PHPUnit\Framework\TestCase protected $filterEmulate; /** - * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\State|\PHPUnit\Framework\MockObject\MockObject */ protected $appStateMock; diff --git a/app/code/Magento/Widget/Test/Unit/Model/Template/FilterTest.php b/app/code/Magento/Widget/Test/Unit/Model/Template/FilterTest.php index db2f468da663c..52995e7168153 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/Template/FilterTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/Template/FilterTest.php @@ -21,27 +21,27 @@ class FilterTest extends \PHPUnit\Framework\TestCase protected $objectManagerHelper; /** - * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\Store|\PHPUnit\Framework\MockObject\MockObject */ protected $storeMock; /** - * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var StoreManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $storeManagerMock; /** - * @var \Magento\Widget\Model\ResourceModel\Widget|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Widget\Model\ResourceModel\Widget|\PHPUnit\Framework\MockObject\MockObject */ protected $widgetResourceMock; /** - * @var \Magento\Widget\Model\Widget|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Widget\Model\Widget|\PHPUnit\Framework\MockObject\MockObject */ protected $widgetMock; /** - * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\LayoutInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $layoutMock; @@ -235,11 +235,11 @@ protected function generalForGenerateWidget( /** * @param string $returnedResult - * @return \Magento\Widget\Block\BlockInterface|\PHPUnit_Framework_MockObject_MockObject + * @return \Magento\Widget\Block\BlockInterface|\PHPUnit\Framework\MockObject\MockObject */ protected function getBlockMock($returnedResult = '') { - /** @var \Magento\Widget\Block\BlockInterface|\PHPUnit_Framework_MockObject_MockObject $blockMock */ + /** @var \Magento\Widget\Block\BlockInterface|\PHPUnit\Framework\MockObject\MockObject $blockMock */ $blockMock = $this->getMockBuilder(\Magento\Widget\Block\BlockInterface::class) ->setMethods(['toHtml']) ->getMockForAbstractClass(); diff --git a/app/code/Magento/Widget/Test/Unit/Model/Widget/InstanceTest.php b/app/code/Magento/Widget/Test/Unit/Model/Widget/InstanceTest.php index a2a9a88bff774..9baf599134912 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/Widget/InstanceTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/Widget/InstanceTest.php @@ -15,16 +15,16 @@ class InstanceTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Widget\Model\Config\Data|PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Widget\Model\Config\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $_widgetModelMock; /** - * @var \Magento\Framework\View\FileSystem|PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\FileSystem|\PHPUnit\Framework\MockObject\MockObject */ protected $_viewFileSystemMock; - /** @var \Magento\Widget\Model\NamespaceResolver |PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Widget\Model\NamespaceResolver|\PHPUnit\Framework\MockObject\MockObject */ protected $_namespaceResolver; /** @@ -36,16 +36,16 @@ class InstanceTest extends \PHPUnit\Framework\TestCase protected $_readerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $_cacheTypesListMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $_directoryMock; - /** @var \Magento\Framework\Serialize\Serializer\Json | \PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\Serialize\Serializer\Json|\PHPUnit\Framework\MockObject\MockObject */ private $serializer; protected function setUp() diff --git a/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php b/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php index 850a3fbe83211..2228177836695 100644 --- a/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php +++ b/app/code/Magento/Widget/Test/Unit/Model/WidgetTest.php @@ -13,12 +13,12 @@ class WidgetTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Widget\Model\Config\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Widget\Model\Config\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $dataStorageMock; /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Escaper|\PHPUnit\Framework\MockObject\MockObject */ private $escaperMock; diff --git a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml new file mode 100644 index 0000000000000..690b6b8bc2b59 --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.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="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup"> + <annotations> + <description>Assert "Add to Wish List" icon is clickable in category product listing</description> + </annotations> + + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> + <click selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForErrorMessageIsVisible"/> + <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="You must login or register to add items to your wishlist." stepKey="assertErrorMessage"/> + <seeInCurrentUrl url="{{StorefrontCustomerSignInPage.url}}" stepKey="assertCustomerLoginPageUrl"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/ConfProdAddToCartWishListWithUnselectedAttrTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/ConfProdAddToCartWishListWithUnselectedAttrTest.xml index d1d9a439c335d..4e4d5c1a0696f 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/ConfProdAddToCartWishListWithUnselectedAttrTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/ConfProdAddToCartWishListWithUnselectedAttrTest.xml @@ -38,7 +38,7 @@ </actionGroup> <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!--Login as customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/ConfigurableProductChildImageShouldBeShownOnWishListTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/ConfigurableProductChildImageShouldBeShownOnWishListTest.xml index c9c539d215165..9d6482248df0a 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/ConfigurableProductChildImageShouldBeShownOnWishListTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/ConfigurableProductChildImageShouldBeShownOnWishListTest.xml @@ -32,7 +32,7 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="customer" stepKey="deleteCustomer"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <waitForPageLoad stepKey="waitForProductIndexPageLoad"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml index 82021e75e0983..2a84043584dbe 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontAddMultipleStoreProductsToWishlistTest.xml @@ -48,7 +48,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsFilters"/> <!--Logout everywhere--> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> </after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleDynamicProductFromWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleDynamicProductFromWishlistTest.xml index f5d7eb4c6ed02..3ff3fe0f379ce 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleDynamicProductFromWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleDynamicProductFromWishlistTest.xml @@ -62,7 +62,7 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleFixedProductFromWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleFixedProductFromWishlistTest.xml index cdd86bfecccc8..a23788d2c508f 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleFixedProductFromWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteBundleFixedProductFromWishlistTest.xml @@ -55,7 +55,7 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml index 6a718ebdfcf0f..c380bddd2aca8 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml @@ -117,7 +117,10 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- 1. Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeletePersistedWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeletePersistedWishlistTest.xml index f1659baaa4e09..0ead68a6b9144 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeletePersistedWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeletePersistedWishlistTest.xml @@ -32,7 +32,7 @@ <deleteData stepKey="deleteCategory" createDataKey="category"/> <deleteData stepKey="deleteProduct" createDataKey="product"/> <deleteData stepKey="deleteCustomer" createDataKey="customer"/> - <actionGroup ref="logout" stepKey="adminLogout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveConfigurableProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveConfigurableProductFromShoppingCartToWishlistTest.xml index 0f94a08328c95..a5081ca2ad338 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveConfigurableProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveConfigurableProductFromShoppingCartToWishlistTest.xml @@ -119,7 +119,7 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml index 3a823efbcdf61..6af7c6eae2c2a 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml @@ -52,8 +52,8 @@ <scrollTo selector="{{AdminProductFormBundleSection.contentDropDown}}" stepKey="scrollToBundleSection"/> <selectOption userInput="Separately" selector="{{AdminProductFormBundleSection.shipmentType}}" stepKey="selectSeparately"/> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - <magentoCLI stepKey="reindex" command="indexer:reindex"/> - <magentoCLI stepKey="flushCache" command="cache:flush"/> + + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> <!-- Delete data --> @@ -62,7 +62,7 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml index 2d83043f81318..8b94c42106a6a 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml @@ -43,8 +43,8 @@ <requiredEntity createDataKey="createBundleOption1_1"/> <requiredEntity createDataKey="simpleProduct2"/> </createData> - <magentoCLI stepKey="reindex" command="indexer:reindex"/> - <magentoCLI stepKey="flushCache" command="cache:flush"/> + + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> <!-- Delete data --> @@ -53,7 +53,7 @@ <deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> <deleteData createDataKey="simpleProduct1" stepKey="deleteProduct1"/> <deleteData createDataKey="simpleProduct2" stepKey="deleteProduct2"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveVirtualProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveVirtualProductFromShoppingCartToWishlistTest.xml index ad10b8d01bbbd..5c2762f39dde6 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveVirtualProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveVirtualProductFromShoppingCartToWishlistTest.xml @@ -32,7 +32,7 @@ <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- 1. Login as a customer --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml index bb566ef2d03a4..329978462c107 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml @@ -15,44 +15,39 @@ <title value="Customer should be able to share a persistent wishlist"/> <description value="Customer should be able to share a persistent wishlist"/> <severity value="AVERAGE"/> - <group value="wishlist"/> - <testCaseId value="MC-13976"/> + <testCaseId value="MC-27621"/> <group value="wishlist"/> <group value="mtf_migrated"/> </annotations> <before> - <createData entity="SimpleSubCategory" stepKey="category"/> - <createData entity="SimpleProduct" stepKey="product"> - <requiredEntity createDataKey="category"/> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="Simple_US_Customer" stepKey="customer"/> - - <!-- Perform reindex and flush cache --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> </before> <after> - <deleteData createDataKey="category" stepKey="deleteCategory"/> - <deleteData createDataKey="product" stepKey="deleteProduct"/> - <deleteData createDataKey="customer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <!-- Customer logout --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> </after> <!-- Sign in as customer --> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> - <argument name="Customer" value="$$customer$$"/> + <argument name="Customer" value="$createCustomer$"/> </actionGroup> <actionGroup ref="OpenProductFromCategoryPageActionGroup" stepKey="openProductFromCategory"> - <argument name="category" value="$$category$$"/> - <argument name="product" value="$$product$$"/> + <argument name="category" value="$createCategory$"/> + <argument name="product" value="$createProduct$"/> </actionGroup> <actionGroup ref="StorefrontCustomerAddProductToWishlistActionGroup" stepKey="addToWishlistProduct"> - <argument name="productVar" value="$$product$$"/> + <argument name="productVar" value="$createProduct$"/> </actionGroup> <actionGroup ref="StorefrontCustomerShareWishlistActionGroup" stepKey="shareWishlist"/> - - <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </test> </tests> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/WishListWithDisabledProductTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/WishListWithDisabledProductTest.xml index 3aabb9e94c364..f9072402dbd73 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/WishListWithDisabledProductTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/WishListWithDisabledProductTest.xml @@ -26,7 +26,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> <argument name="Customer" value="$$createCustomer$$"/> diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Adminhtml/Widget/Grid/Column/Filter/TextTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Adminhtml/Widget/Grid/Column/Filter/TextTest.php index 69283cd701119..2454a2e84e5af 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Adminhtml/Widget/Grid/Column/Filter/TextTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Adminhtml/Widget/Grid/Column/Filter/TextTest.php @@ -10,7 +10,7 @@ class TextTest extends \PHPUnit\Framework\TestCase { - /** @var Text | \PHPUnit_Framework_MockObject_MockObject */ + /** @var Text|\PHPUnit\Framework\MockObject\MockObject */ private $textFilterBlock; protected function setUp() diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Cart/Item/Renderer/Actions/MoveToWishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Cart/Item/Renderer/Actions/MoveToWishlistTest.php index cd4fe2d04cbbe..f454b62024680 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Cart/Item/Renderer/Actions/MoveToWishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Cart/Item/Renderer/Actions/MoveToWishlistTest.php @@ -16,7 +16,7 @@ class MoveToWishlistTest extends \PHPUnit\Framework\TestCase */ protected $model; - /** @var Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Data|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistHelperMock; protected function setUp() @@ -50,7 +50,7 @@ public function testGetMoveFromCartParams() $json = '{json;}'; /** - * @var Item|\PHPUnit_Framework_MockObject_MockObject $itemMock + * @var Item|\PHPUnit\Framework\MockObject\MockObject $itemMock */ $itemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class) ->disableOriginalConstructor() diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Customer/SidebarTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Customer/SidebarTest.php index 92c36470d7f7f..546ca009a6b1a 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Customer/SidebarTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Customer/SidebarTest.php @@ -11,12 +11,12 @@ class SidebarTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Block\Product\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Block\Product\Context|\PHPUnit\Framework\MockObject\MockObject */ private $productContext; /** - * @var \Magento\Framework\App\Http\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Http\Context|\PHPUnit\Framework\MockObject\MockObject */ private $httpContext; @@ -26,7 +26,7 @@ class SidebarTest extends \PHPUnit\Framework\TestCase private $block; /** - * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\LayoutInterface|\PHPUnit\Framework\MockObject\MockObject */ private $layout; diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Customer/Wishlist/Item/OptionsTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Customer/Wishlist/Item/OptionsTest.php index 36c51547c5a42..9067f042445d9 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Customer/Wishlist/Item/OptionsTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Customer/Wishlist/Item/OptionsTest.php @@ -13,12 +13,12 @@ class OptionsTest extends \PHPUnit\Framework\TestCase const TEST_HELPER_CLASS_NAME = 'testHelperClass'; /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Escaper|\PHPUnit\Framework\MockObject\MockObject */ private $escaperMock; /** - * @var \Magento\Framework\App\Http\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Http\Context|\PHPUnit\Framework\MockObject\MockObject */ private $httpContextMock; @@ -28,12 +28,12 @@ class OptionsTest extends \PHPUnit\Framework\TestCase private $block; /** - * @var \Magento\Catalog\Helper\Product\ConfigurationPool|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Helper\Product\ConfigurationPool|\PHPUnit\Framework\MockObject\MockObject */ private $helperPoolMock; /** - * @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject */ private $itemMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Item/ConfigureTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Item/ConfigureTest.php index 6aa60aa3be571..9847fff4135f6 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Item/ConfigureTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Item/ConfigureTest.php @@ -15,17 +15,17 @@ class ConfigureTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $registryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $contextMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $wishlistDataMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Rss/EmailLinkTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Rss/EmailLinkTest.php index 030669202f44d..cf73945a9feef 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Rss/EmailLinkTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Rss/EmailLinkTest.php @@ -16,14 +16,14 @@ class EmailLinkTest extends \PHPUnit\Framework\TestCase /** @var ObjectManagerHelper */ protected $objectManagerHelper; - /** @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistHelper; - /** @var \Magento\Framework\App\Rss\UrlBuilderInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\App\Rss\UrlBuilderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlBuilder; /** - * @var \Magento\Framework\Url\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Url\EncoderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlEncoder; diff --git a/app/code/Magento/Wishlist/Test/Unit/Block/Rss/LinkTest.php b/app/code/Magento/Wishlist/Test/Unit/Block/Rss/LinkTest.php index df63367a23cba..6eb5bf0ad0cd5 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Block/Rss/LinkTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Block/Rss/LinkTest.php @@ -16,17 +16,17 @@ class LinkTest extends \PHPUnit\Framework\TestCase /** @var ObjectManagerHelper */ protected $objectManagerHelper; - /** @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistHelper; - /** @var \Magento\Framework\App\Rss\UrlBuilderInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\App\Rss\UrlBuilderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlBuilder; - /** @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $scopeConfig; /** - * @var \Magento\Framework\Url\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Url\EncoderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlEncoder; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php index 2df44a912a09c..341ca72cc2ef2 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AllcartTest.php @@ -13,47 +13,47 @@ class AllcartTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Wishlist\Controller\WishlistProviderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\WishlistProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; /** - * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit\Framework\MockObject\MockObject */ protected $itemCarrier; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Response\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $response; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirectMock; /** - * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit\Framework\MockObject\MockObject */ protected $resultForwardMock; @@ -189,7 +189,7 @@ public function testExecutePassed() { $url = 'http://redirect-url.com'; $wishlist = $this->createMock(\Magento\Wishlist\Model\Wishlist::class); - + $this->formKeyValidator->expects($this->once()) ->method('validate') ->with($this->request) diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php index c1f1378c22da6..093f0d8d6b8f8 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/CartTest.php @@ -21,97 +21,97 @@ class CartTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $contextMock; /** - * @var \Magento\Wishlist\Controller\WishlistProviderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\WishlistProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProviderMock; /** - * @var \Magento\Wishlist\Model\LocaleQuantityProcessor|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\LocaleQuantityProcessor|\PHPUnit\Framework\MockObject\MockObject */ protected $quantityProcessorMock; /** - * @var \Magento\Wishlist\Model\ItemFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ItemFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $itemFactoryMock; /** - * @var \Magento\Checkout\Model\Cart|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Checkout\Model\Cart|\PHPUnit\Framework\MockObject\MockObject */ protected $checkoutCartMock; /** - * @var \Magento\Wishlist\Model\Item\OptionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Item\OptionFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $optionFactoryMock; /** - * @var \Magento\Catalog\Helper\Product|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Helper\Product|\PHPUnit\Framework\MockObject\MockObject */ protected $productHelperMock; /** - * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Escaper|\PHPUnit\Framework\MockObject\MockObject */ protected $escaperMock; /** - * @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $helperMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $requestMock; /** - * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $redirectMock; /** - * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $objectManagerMock; /** - * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManagerMock; /** - * @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\UrlInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlMock; /** - * @var \Magento\Checkout\Helper\Cart|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Checkout\Helper\Cart|\PHPUnit\Framework\MockObject\MockObject */ protected $cartHelperMock; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirectMock; /** - * @var \Magento\Framework\Controller\Result\Json|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Json|\PHPUnit\Framework\MockObject\MockObject */ protected $resultJsonMock; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php index 52af38dee0ed3..82a5559ceedf4 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/FromcartTest.php @@ -31,57 +31,57 @@ class FromcartTest extends \PHPUnit\Framework\TestCase protected $controller; /** - * @var Context | \PHPUnit_Framework_MockObject_MockObject + * @var Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; /** - * @var WishlistProviderInterface | \PHPUnit_Framework_MockObject_MockObject + * @var WishlistProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; /** - * @var WishlistHelper | \PHPUnit_Framework_MockObject_MockObject + * @var WishlistHelper|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistHelper; /** - * @var CheckoutCart | \PHPUnit_Framework_MockObject_MockObject + * @var CheckoutCart|\PHPUnit\Framework\MockObject\MockObject */ protected $cart; /** - * @var CartHelper | \PHPUnit_Framework_MockObject_MockObject + * @var CartHelper|\PHPUnit\Framework\MockObject\MockObject */ protected $cartHelper; /** - * @var Escaper | \PHPUnit_Framework_MockObject_MockObject + * @var Escaper|\PHPUnit\Framework\MockObject\MockObject */ protected $escaper; /** - * @var Http | \PHPUnit_Framework_MockObject_MockObject + * @var Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var MessageManager | \PHPUnit_Framework_MockObject_MockObject + * @var MessageManager|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; /** - * @var ResultFactory | \PHPUnit_Framework_MockObject_MockObject + * @var ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactory; /** - * @var ResultRedirect | \PHPUnit_Framework_MockObject_MockObject + * @var ResultRedirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirect; /** - * @var Validator|\PHPUnit_Framework_MockObject_MockObject + * @var Validator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; @@ -363,7 +363,7 @@ protected function prepareContext() * @param string $productName * @param DataObject $dataObjectMock * @param int $itemId - * @return \PHPUnit_Framework_MockObject_MockObject + * @return \PHPUnit\Framework\MockObject\MockObject */ protected function createQuoteMock($productId, $productName, $dataObjectMock, $itemId) { diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php index 7c6ba740aa18d..f850154f086a9 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/IndexTest.php @@ -13,42 +13,42 @@ class IndexTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Response\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $response; /** - * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; /** - * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\App\Response\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $redirect; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Result\Page|\PHPUnit\Framework\MockObject\MockObject */ protected $resultPageMock; /** - * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout|\PHPUnit\Framework\MockObject\MockObject */ protected $layoutMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/PluginTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/PluginTest.php index 53b9ba7d846b1..fb58777690bd1 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/PluginTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/PluginTest.php @@ -16,32 +16,32 @@ class PluginTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** - * @var \Magento\Wishlist\Model\AuthenticationStateInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\AuthenticationStateInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $authenticationState; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $config; /** - * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $redirector; /** - * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php index 2f4d0e6ba48ab..9029ae2bb82bf 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php @@ -13,52 +13,52 @@ class RemoveTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Store\App\Response\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\App\Response\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $redirect; /** - * @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\ObjectManager|\PHPUnit\Framework\MockObject\MockObject */ protected $om; /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\Manager|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; /** - * @var \Magento\Framework\Url|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Url|\PHPUnit\Framework\MockObject\MockObject */ protected $url; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirectMock; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php index c70c2a1a6a9b6..d3efd1f192f27 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php @@ -31,55 +31,55 @@ */ class SendTest extends \PHPUnit\Framework\TestCase { - /** @var Send |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Send|\PHPUnit\Framework\MockObject\MockObject */ protected $model; - /** @var ActionContext |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ActionContext|\PHPUnit\Framework\MockObject\MockObject */ protected $context; - /** @var FormKeyValidator |\PHPUnit_Framework_MockObject_MockObject */ + /** @var FormKeyValidator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; - /** @var WishlistProviderInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var WishlistProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; - /** @var Store |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Store|\PHPUnit\Framework\MockObject\MockObject */ protected $store; - /** @var ResultFactory |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactory; - /** @var ResultRedirect |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ResultRedirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirect; - /** @var ResultLayout |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ResultLayout|\PHPUnit\Framework\MockObject\MockObject */ protected $resultLayout; - /** @var RequestInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $request; - /** @var ManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; - /** @var CustomerData |\PHPUnit_Framework_MockObject_MockObject */ + /** @var CustomerData|\PHPUnit\Framework\MockObject\MockObject */ protected $customerData; - /** @var UrlInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var UrlInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $url; - /** @var TransportInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var TransportInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $transport; - /** @var EventManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var EventManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $eventManager; - /** @var CaptchaHelper |\PHPUnit_Framework_MockObject_MockObject */ + /** @var CaptchaHelper|\PHPUnit\Framework\MockObject\MockObject */ protected $captchaHelper; - /** @var CaptchaModel |\PHPUnit_Framework_MockObject_MockObject */ + /** @var CaptchaModel|\PHPUnit\Framework\MockObject\MockObject */ protected $captchaModel; - /** @var Session |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/ShareTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/ShareTest.php index cf97489f1fbc0..6d7746a1f8e76 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/ShareTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/ShareTest.php @@ -16,17 +16,17 @@ class ShareTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $customerSessionMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $contextMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php index b6fd509214897..815e6bbe0adc6 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php @@ -13,62 +13,62 @@ class UpdateItemOptionsTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Catalog\Model\ProductRepository|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ProductRepository|\PHPUnit\Framework\MockObject\MockObject */ protected $productRepository; /** - * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\WishlistProvider|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; /** - * @var \Magento\Framework\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Action\Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $request; /** - * @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\ObjectManager|\PHPUnit\Framework\MockObject\MockObject */ protected $om; /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\Manager|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; /** - * @var \Magento\Framework\Url|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Url|\PHPUnit\Framework\MockObject\MockObject */ protected $url; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** - * @var \Magento\Framework\Event\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Event\Manager|\PHPUnit\Framework\MockObject\MockObject */ protected $eventManager; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirectMock; /** - * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Form\FormKey\Validator|\PHPUnit\Framework\MockObject\MockObject */ protected $formKeyValidator; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateTest.php index 88aeec5e5a924..738131b5c2930 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateTest.php @@ -21,7 +21,7 @@ use Magento\Wishlist\Model\LocaleQuantityProcessor; use Magento\Wishlist\Model\Wishlist; use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject as MockObject; +use PHPUnit\Framework\MockObject\MockObject; /** * Test for upate controller wishlist diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php index 24438dbc71d99..d5ac5e9485424 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/AllcartTest.php @@ -26,37 +26,37 @@ class AllcartTest extends \PHPUnit\Framework\TestCase protected $context; /** - * @var \Magento\Wishlist\Controller\Shared\WishlistProvider|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Controller\Shared\WishlistProvider|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProviderMock; /** - * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ItemCarrier|\PHPUnit\Framework\MockObject\MockObject */ protected $itemCarrierMock; /** - * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistMock; /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit\Framework\MockObject\MockObject */ protected $requestMock; /** - * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactoryMock; /** - * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirectMock; /** - * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit\Framework\MockObject\MockObject */ protected $resultForwardMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php index c65f166957c5f..eba5666114139 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php @@ -30,55 +30,55 @@ */ class CartTest extends \PHPUnit\Framework\TestCase { - /** @var SharedCart |\PHPUnit_Framework_MockObject_MockObject */ + /** @var SharedCart|\PHPUnit\Framework\MockObject\MockObject */ protected $model; - /** @var RequestInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $request; - /** @var ManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; - /** @var ActionContext |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ActionContext|\PHPUnit\Framework\MockObject\MockObject */ protected $context; - /** @var Cart |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Cart|\PHPUnit\Framework\MockObject\MockObject */ protected $cart; - /** @var CartHelper |\PHPUnit_Framework_MockObject_MockObject */ + /** @var CartHelper|\PHPUnit\Framework\MockObject\MockObject */ protected $cartHelper; - /** @var Quote | \PHPUnit_Framework_MockObject_MockObject */ + /** @var Quote|\PHPUnit\Framework\MockObject\MockObject */ protected $quote; - /** @var OptionCollection |\PHPUnit_Framework_MockObject_MockObject */ + /** @var OptionCollection|\PHPUnit\Framework\MockObject\MockObject */ protected $optionCollection; - /** @var OptionFactory |\PHPUnit_Framework_MockObject_MockObject */ + /** @var OptionFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $optionFactory; - /** @var Option |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Option|\PHPUnit\Framework\MockObject\MockObject */ protected $option; - /** @var ItemFactory |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ItemFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $itemFactory; - /** @var Item |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Item|\PHPUnit\Framework\MockObject\MockObject */ protected $item; - /** @var Escaper |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Escaper|\PHPUnit\Framework\MockObject\MockObject */ protected $escaper; - /** @var RedirectInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var RedirectInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $redirect; - /** @var ResultFactory |\PHPUnit_Framework_MockObject_MockObject */ + /** @var ResultFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $resultFactory; - /** @var Redirect |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Redirect|\PHPUnit\Framework\MockObject\MockObject */ protected $resultRedirect; - /** @var Product |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Product|\PHPUnit\Framework\MockObject\MockObject */ protected $product; protected function setUp() diff --git a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php index 6d90d8b1a5fed..3ef2833ded21f 100644 --- a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php @@ -26,19 +26,19 @@ class WishlistTest extends \PHPUnit\Framework\TestCase /** @var Wishlist */ private $model; - /** @var Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Data|\PHPUnit\Framework\MockObject\MockObject */ private $wishlistHelperMock; - /** @var Sidebar|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Sidebar|\PHPUnit\Framework\MockObject\MockObject */ private $sidebarMock; - /** @var Image|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Image|\PHPUnit\Framework\MockObject\MockObject */ private $catalogImageHelperMock; - /** @var ViewInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var ViewInterface|\PHPUnit\Framework\MockObject\MockObject */ private $viewMock; - /** @var \Magento\Catalog\Block\Product\ImageBuilder|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Catalog\Block\Product\ImageBuilder|\PHPUnit\Framework\MockObject\MockObject */ private $itemResolver; protected function setUp() @@ -120,7 +120,7 @@ public function testGetSectionData() ], ]; - /** @var Item|\PHPUnit_Framework_MockObject_MockObject $itemMock */ + /** @var Item|\PHPUnit\Framework\MockObject\MockObject $itemMock */ $itemMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->disableOriginalConstructor() ->getMock(); @@ -133,7 +133,7 @@ public function testGetSectionData() $this->viewMock->expects($this->once()) ->method('loadLayout'); - /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $itemCollectionMock */ + /** @var Collection|\PHPUnit\Framework\MockObject\MockObject $itemCollectionMock */ $itemCollectionMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -161,7 +161,7 @@ public function testGetSectionData() ->method('getIterator') ->willReturn(new \ArrayIterator($items)); - /** @var Product|\PHPUnit_Framework_MockObject_MockObject $productMock */ + /** @var Product|\PHPUnit\Framework\MockObject\MockObject $productMock */ $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() ->getMock(); @@ -229,7 +229,7 @@ public function testGetSectionData() ->method('isVisibleInSiteVisibility') ->willReturn($productIsVisible); - /** @var AbstractType|\PHPUnit_Framework_MockObject_MockObject $productTypeMock */ + /** @var AbstractType|\PHPUnit\Framework\MockObject\MockObject $productTypeMock */ $productTypeMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Type\AbstractType::class) ->disableOriginalConstructor() ->setMethods(['hasRequiredOptions']) @@ -276,7 +276,7 @@ public function testGetSectionDataWithTwoItems() $itemAddParams = ['add_params']; $itemRemoveParams = ['remove_params']; - /** @var Item|\PHPUnit_Framework_MockObject_MockObject $itemMock */ + /** @var Item|\PHPUnit\Framework\MockObject\MockObject $itemMock */ $itemMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->disableOriginalConstructor() ->getMock(); @@ -331,7 +331,7 @@ public function testGetSectionDataWithTwoItems() $this->viewMock->expects($this->once()) ->method('loadLayout'); - /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $itemCollectionMock */ + /** @var Collection|\PHPUnit\Framework\MockObject\MockObject $itemCollectionMock */ $itemCollectionMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -359,7 +359,7 @@ public function testGetSectionDataWithTwoItems() ->method('getIterator') ->willReturn(new \ArrayIterator($items)); - /** @var Product|\PHPUnit_Framework_MockObject_MockObject $productMock */ + /** @var Product|\PHPUnit\Framework\MockObject\MockObject $productMock */ $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() ->getMock(); @@ -428,7 +428,7 @@ public function testGetSectionDataWithTwoItems() $productMock->expects($this->never()) ->method('isVisibleInSiteVisibility'); - /** @var AbstractType|\PHPUnit_Framework_MockObject_MockObject $productTypeMock */ + /** @var AbstractType|\PHPUnit\Framework\MockObject\MockObject $productTypeMock */ $productTypeMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Type\AbstractType::class) ->disableOriginalConstructor() ->setMethods(['hasRequiredOptions']) diff --git a/app/code/Magento/Wishlist/Test/Unit/DataProvider/Product/Collector/ButtonTest.php b/app/code/Magento/Wishlist/Test/Unit/DataProvider/Product/Collector/ButtonTest.php index 8fd514796d949..89114fe34dc62 100644 --- a/app/code/Magento/Wishlist/Test/Unit/DataProvider/Product/Collector/ButtonTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/DataProvider/Product/Collector/ButtonTest.php @@ -23,13 +23,13 @@ class ButtonTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Wishlist\Ui\DataProvider\Product\Collector\Button */ private $button; - /** @var ProductRenderExtensionFactory|\PHPUnit_Framework_MockObject_MockObject */ + /** @var ProductRenderExtensionFactory|\PHPUnit\Framework\MockObject\MockObject */ private $productRenderExtensionFactoryMock; - /** @var Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var Data|\PHPUnit\Framework\MockObject\MockObject */ private $wishlistHelperMock; - /** @var ButtonInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject */ + /** @var ButtonInterfaceFactory|\PHPUnit\Framework\MockObject\MockObject */ private $buttonInterfaceFactoryMock; protected function setUp() diff --git a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php index 263f3c5d1688e..3a43705120e9e 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php @@ -28,43 +28,43 @@ class DataTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Wishlist\Helper\Data */ protected $model; - /** @var WishlistProviderInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var WishlistProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistProvider; - /** @var Registry |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Registry|\PHPUnit\Framework\MockObject\MockObject */ protected $coreRegistry; - /** @var PostHelper |\PHPUnit_Framework_MockObject_MockObject */ + /** @var PostHelper|\PHPUnit\Framework\MockObject\MockObject */ protected $postDataHelper; - /** @var WishlistItem |\PHPUnit_Framework_MockObject_MockObject */ + /** @var WishlistItem|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistItem; - /** @var Product |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Product|\PHPUnit\Framework\MockObject\MockObject */ protected $product; - /** @var StoreManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var StoreManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $storeManager; - /** @var Store |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Store|\PHPUnit\Framework\MockObject\MockObject */ protected $store; - /** @var UrlInterface |\PHPUnit_Framework_MockObject_MockObject */ + /** @var UrlInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlBuilder; - /** @var Wishlist |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Wishlist|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlist; - /** @var EncoderInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var EncoderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlEncoderMock; - /** @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $requestMock; - /** @var Context |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Context|\PHPUnit\Framework\MockObject\MockObject */ protected $context; - /** @var Session |\PHPUnit_Framework_MockObject_MockObject */ + /** @var Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** @@ -180,7 +180,7 @@ public function testGetConfigureUrl() { $url = 'http://magento2ce/wishlist/index/configure/id/4/product_id/30/'; - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $wishlistItem */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $wishlistItem */ $wishlistItem = $this->createPartialMock( \Magento\Wishlist\Model\Item::class, ['getWishlistItemId', 'getProductId'] diff --git a/app/code/Magento/Wishlist/Test/Unit/Helper/RssTest.php b/app/code/Magento/Wishlist/Test/Unit/Helper/RssTest.php index d0397be83fac7..622c151b2f79a 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Helper/RssTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Helper/RssTest.php @@ -16,42 +16,42 @@ class RssTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistFactoryMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $requestMock; /** - * @var \Magento\Framework\Url\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Url\DecoderInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlDecoderMock; /** - * @var \Magento\Customer\Api\Data\CustomerInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Api\Data\CustomerInterfaceFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $customerFactoryMock; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSessionMock; /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $customerRepositoryMock; /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Module\Manager|\PHPUnit\Framework\MockObject\MockObject */ protected $moduleManagerMock; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $scopeConfigMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/ConfigTest.php index 914d9aca65602..fc9efb38747f9 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/ConfigTest.php @@ -15,17 +15,17 @@ class ConfigTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $_scopeConfig; /** - * @var \Magento\Catalog\Model\Config|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Config|\PHPUnit\Framework\MockObject\MockObject */ protected $_catalogConfig; /** - * @var \Magento\Catalog\Model\Attribute\Config|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Attribute\Config|\PHPUnit\Framework\MockObject\MockObject */ protected $_attributeConfig; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/ItemCarrierTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/ItemCarrierTest.php index 71ae2d182d0e4..3b9e734c89598 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/ItemCarrierTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/ItemCarrierTest.php @@ -15,31 +15,31 @@ class ItemCarrierTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Wishlist\Model\ItemCarrier */ protected $model; - /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $sessionMock; - /** @var \Magento\Wishlist\Model\LocaleQuantityProcessor|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Wishlist\Model\LocaleQuantityProcessor|\PHPUnit\Framework\MockObject\MockObject */ protected $quantityProcessorMock; - /** @var \Magento\Checkout\Model\Cart|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Checkout\Model\Cart|\PHPUnit\Framework\MockObject\MockObject */ protected $cartMock; - /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $loggerMock; - /** @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistHelperMock; - /** @var \Magento\Checkout\Helper\Cart|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Checkout\Helper\Cart|\PHPUnit\Framework\MockObject\MockObject */ protected $cartHelperMock; - /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\UrlInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $urlBuilderMock; - /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $managerMock; - /** @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\App\Response\RedirectInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $redirectMock; protected function setUp() @@ -97,23 +97,23 @@ public function testMoveAllToCart() $indexUrl = 'index_url'; $redirectUrl = 'redirect_url'; - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemOneMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemOneMock */ $itemOneMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemTwoMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemTwoMock */ $itemTwoMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productOneMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productOneMock */ $productOneMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productTwoMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productTwoMock */ $productTwoMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() @@ -128,7 +128,7 @@ public function testMoveAllToCart() $collection = [$itemOneMock, $itemTwoMock]; - /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject $wishlistMock */ + /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject $wishlistMock */ $wishlistMock = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class) ->disableOriginalConstructor() ->getMock(); @@ -145,7 +145,7 @@ public function testMoveAllToCart() ->method('getId') ->willReturn($wishlistId); - /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var Collection|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $collectionMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -236,7 +236,7 @@ public function testMoveAllToCart() ->method('save') ->willReturnSelf(); - /** @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var \Magento\Quote\Model\Quote|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) ->disableOriginalConstructor() ->getMock(); @@ -272,23 +272,23 @@ public function testMoveAllToCartWithNotSalableAndOptions() $redirectUrl = 'redirect_url'; $sharingCode = 'sharingcode'; - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemOneMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemOneMock */ $itemOneMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemTwoMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemTwoMock */ $itemTwoMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productOneMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productOneMock */ $productOneMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productTwoMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productTwoMock */ $productTwoMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() @@ -303,7 +303,7 @@ public function testMoveAllToCartWithNotSalableAndOptions() $collection = [$itemOneMock, $itemTwoMock]; - /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject $wishlistMock */ + /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject $wishlistMock */ $wishlistMock = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class) ->setMethods(['isOwner', 'getItemCollection', 'getId', 'getSharingCode', 'save']) ->disableOriginalConstructor() @@ -318,7 +318,7 @@ public function testMoveAllToCartWithNotSalableAndOptions() ->with($sessionCustomerId) ->willReturn($isOwner); - /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var Collection|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $collectionMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -382,7 +382,7 @@ public function testMoveAllToCartWithNotSalableAndOptions() ->with($this->cartMock, $isOwner) ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('Localized Exception.'))); - /** @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var \Magento\Quote\Model\Quote|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) ->disableOriginalConstructor() ->getMock(); @@ -391,7 +391,7 @@ public function testMoveAllToCartWithNotSalableAndOptions() ->method('getQuote') ->willReturn($quoteMock); - /** @var \Magento\Quote\Model\Quote\Item|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var \Magento\Quote\Model\Quote\Item|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $itemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class) ->disableOriginalConstructor() ->getMock(); @@ -467,23 +467,23 @@ public function testMoveAllToCartWithException() $isOwner = true; $indexUrl = 'index_url'; - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemOneMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemOneMock */ $itemOneMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Wishlist\Model\Item|\PHPUnit_Framework_MockObject_MockObject $itemTwoMock */ + /** @var \Magento\Wishlist\Model\Item|\PHPUnit\Framework\MockObject\MockObject $itemTwoMock */ $itemTwoMock = $this->getMockBuilder(\Magento\Wishlist\Model\Item::class) ->setMethods(['getProduct', 'unsProduct', 'getId', 'setQty', 'addToCart', 'delete', 'getProductUrl']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productOneMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productOneMock */ $productOneMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() ->getMock(); - /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject $productTwoMock */ + /** @var \Magento\Catalog\Model\Product|\PHPUnit\Framework\MockObject\MockObject $productTwoMock */ $productTwoMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->setMethods(['getDisableAddToCart', 'setDisableAddToCart', 'getName']) ->disableOriginalConstructor() @@ -498,7 +498,7 @@ public function testMoveAllToCartWithException() $collection = [$itemOneMock, $itemTwoMock]; - /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject $wishlistMock */ + /** @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject $wishlistMock */ $wishlistMock = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class) ->disableOriginalConstructor() ->getMock(); @@ -515,7 +515,7 @@ public function testMoveAllToCartWithException() ->method('getId') ->willReturn($wishlistId); - /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var Collection|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $collectionMock = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Item\Collection::class) ->disableOriginalConstructor() ->getMock(); @@ -623,7 +623,7 @@ public function testMoveAllToCartWithException() ->method('save') ->willReturnSelf(); - /** @var \Magento\Quote\Model\Quote|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + /** @var \Magento\Quote\Model\Quote|\PHPUnit\Framework\MockObject\MockObject $collectionMock */ $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/ItemTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/ItemTest.php index 9876b3f6bb75e..29f4fbf4e4741 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/ItemTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/ItemTest.php @@ -15,52 +15,52 @@ class ItemTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Registry|\PHPUnit\Framework\MockObject\MockObject */ protected $registry; /** - * @var \Magento\Catalog\Model\ResourceModel\Url|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ResourceModel\Url|\PHPUnit\Framework\MockObject\MockObject */ protected $catalogUrl; /** - * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $productTypeConfig; /** - * @var \Magento\Wishlist\Model\ResourceModel\Item|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ResourceModel\Item|\PHPUnit\Framework\MockObject\MockObject */ protected $resource; /** - * @var \Magento\Wishlist\Model\ResourceModel\Item\Collection|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ResourceModel\Item\Collection|\PHPUnit\Framework\MockObject\MockObject */ protected $collection; /** - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $storeManager; /** - * @var \Magento\Framework\Stdlib\DateTime\DateTime|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Stdlib\DateTime\DateTime|\PHPUnit\Framework\MockObject\MockObject */ protected $date; /** - * @var \Magento\Wishlist\Model\Item\OptionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Item\OptionFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $optionFactory; /** - * @var \Magento\Wishlist\Model\ResourceModel\Item\Option\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\ResourceModel\Item\Option\CollectionFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $itemOptFactory; /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $productRepository; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/LocaleQuantityProcessorTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/LocaleQuantityProcessorTest.php index 6cac17aa8c3da..f262f4419f366 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/LocaleQuantityProcessorTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/LocaleQuantityProcessorTest.php @@ -15,12 +15,12 @@ class LocaleQuantityProcessorTest extends \PHPUnit\Framework\TestCase protected $processor; /** - * @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $resolver; /** - * @var \Magento\Framework\Filter\LocalizedToNormalized|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Filter\LocalizedToNormalized|\PHPUnit\Framework\MockObject\MockObject */ protected $filter; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php index fb0113eb6ae75..62eb2605b3b64 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php @@ -13,30 +13,32 @@ use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Wishlist\Model\Product\AttributeValueProvider; use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit\Framework\MockObject\MockObject; /** - * AttributeValueProviderTest + * Class AttributeValueProviderTest + * + * PHPUnit test case for \Magento\Wishlist\Model\Product\AttributeValueProvider */ class AttributeValueProviderTest extends TestCase { /** - * @var AttributeValueProvider|PHPUnit_Framework_MockObject_MockObject + * @var AttributeValueProvider|MockObject */ private $attributeValueProvider; /** - * @var CollectionFactory|PHPUnit_Framework_MockObject_MockObject + * @var CollectionFactory|MockObject */ private $productCollectionFactoryMock; /** - * @var Product|PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ private $productMock; /** - * @var AdapterInterface|PHPUnit_Framework_MockObject_MockObject + * @var AdapterInterface|MockObject */ private $connectionMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/ResourceModel/Item/CollectionTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/ResourceModel/Item/CollectionTest.php index 197edda298019..92e4a67519090 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/ResourceModel/Item/CollectionTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/ResourceModel/Item/CollectionTest.php @@ -44,7 +44,7 @@ class CollectionTest extends \PHPUnit\Framework\TestCase WHERE (INSTR(product_name_table.value, 'TestProductName'))"; /** - * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject + * @var MetadataPool|\PHPUnit\Framework\MockObject\MockObject */ protected $metadataPool; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/Rss/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/Rss/WishlistTest.php index fc43baa0a67de..b62734b93cbbd 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/Rss/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/Rss/WishlistTest.php @@ -54,7 +54,7 @@ class WishlistTest extends \PHPUnit\Framework\TestCase protected $catalogOutputMock; /** - * @var \Magento\Catalog\Helper\Output|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Helper\Output|\PHPUnit\Framework\MockObject\MockObject */ protected $layoutMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Model/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/Model/WishlistTest.php index eb788efc0d622..be1c11076750a 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/WishlistTest.php @@ -33,7 +33,7 @@ use Magento\Wishlist\Model\ResourceModel\Wishlist\Collection as WishlistCollection; use Magento\Wishlist\Model\Wishlist; use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit\Framework\MockObject\MockObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -42,67 +42,67 @@ class WishlistTest extends TestCase { /** - * @var Registry|PHPUnit_Framework_MockObject_MockObject + * @var Registry|MockObject */ protected $registry; /** - * @var HelperProduct|PHPUnit_Framework_MockObject_MockObject + * @var HelperProduct|MockObject */ protected $productHelper; /** - * @var Data|PHPUnit_Framework_MockObject_MockObject + * @var Data|MockObject */ protected $helper; /** - * @var WishlistResource|PHPUnit_Framework_MockObject_MockObject + * @var WishlistResource|MockObject */ protected $resource; /** - * @var WishlistCollection|PHPUnit_Framework_MockObject_MockObject + * @var WishlistCollection|MockObject */ protected $collection; /** - * @var StoreManagerInterface|PHPUnit_Framework_MockObject_MockObject + * @var StoreManagerInterface|MockObject */ protected $storeManager; /** - * @var DateTime\DateTime|PHPUnit_Framework_MockObject_MockObject + * @var DateTime\DateTime|MockObject */ protected $date; /** - * @var ItemFactory|PHPUnit_Framework_MockObject_MockObject + * @var ItemFactory|MockObject */ protected $itemFactory; /** - * @var CollectionFactory|PHPUnit_Framework_MockObject_MockObject + * @var CollectionFactory|MockObject */ protected $itemsFactory; /** - * @var ProductFactory|PHPUnit_Framework_MockObject_MockObject + * @var ProductFactory|MockObject */ protected $productFactory; /** - * @var Random|PHPUnit_Framework_MockObject_MockObject + * @var Random|MockObject */ protected $mathRandom; /** - * @var DateTime|PHPUnit_Framework_MockObject_MockObject + * @var DateTime|MockObject */ protected $dateTime; /** - * @var ManagerInterface|PHPUnit_Framework_MockObject_MockObject + * @var ManagerInterface|MockObject */ protected $eventDispatcher; @@ -112,22 +112,22 @@ class WishlistTest extends TestCase protected $wishlist; /** - * @var ProductRepositoryInterface|PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|MockObject */ protected $productRepository; /** - * @var Json|PHPUnit_Framework_MockObject_MockObject + * @var Json|MockObject */ protected $serializer; /** - * @var StockItemRepository|PHPUnit_Framework_MockObject_MockObject + * @var StockItemRepository|MockObject */ private $scopeConfig; /** - * @var StockRegistryInterface|PHPUnit_Framework_MockObject_MockObject + * @var StockRegistryInterface|MockObject */ private $stockRegistry; @@ -240,7 +240,7 @@ public function testLoadByCustomerId() } /** - * @param int|Item|PHPUnit_Framework_MockObject_MockObject $itemId + * @param int|Item|MockObject $itemId * @param DataObject $buyRequest * @param null|array|DataObject $param * @throws LocalizedException diff --git a/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php b/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php index e6e14a452a96d..a9d05a7a99eec 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php @@ -19,32 +19,32 @@ class AddToCartTest extends \PHPUnit\Framework\TestCase protected $observer; /** - * @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $helper; /** - * @var \Magento\Checkout\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Checkout\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $checkoutSession; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** - * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistFactory; /** - * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlist; /** - * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; @@ -113,7 +113,7 @@ public function testExecute() $wishlists = $this->getMockBuilder(\Magento\Wishlist\Model\ResourceModel\Wishlist\Collection::class) ->disableOriginalConstructor() ->getMock(); - $loadedWishlist = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist\Item::class) + $loadedWishlist = $this->getMockBuilder(\Magento\Wishlist\Model\Wishlist::class) ->setMethods(['getId', 'delete']) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Wishlist/Test/Unit/Observer/CartUpdateBeforeTest.php b/app/code/Magento/Wishlist/Test/Unit/Observer/CartUpdateBeforeTest.php index 3ca87234b60f9..08614fde9b290 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Observer/CartUpdateBeforeTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Observer/CartUpdateBeforeTest.php @@ -19,32 +19,32 @@ class CartUpdateBeforeTest extends \PHPUnit\Framework\TestCase protected $observer; /** - * @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $helper; /** - * @var \Magento\Checkout\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Checkout\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $checkoutSession; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; /** - * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\WishlistFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlistFactory; /** - * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Model\Wishlist|\PHPUnit\Framework\MockObject\MockObject */ protected $wishlist; /** - * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\ManagerInterface|\PHPUnit\Framework\MockObject\MockObject */ protected $messageManager; diff --git a/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLoginTest.php b/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLoginTest.php index e94f0a8793d57..489fcb48da352 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLoginTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLoginTest.php @@ -16,7 +16,7 @@ class CustomerLoginTest extends \PHPUnit\Framework\TestCase protected $observer; /** - * @var \Magento\Wishlist\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Wishlist\Helper\Data|\PHPUnit\Framework\MockObject\MockObject */ protected $helper; diff --git a/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLogoutTest.php b/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLogoutTest.php index 0933ff2772214..da5ab765a2287 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLogoutTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Observer/CustomerLogoutTest.php @@ -15,7 +15,7 @@ class CustomerLogoutTest extends \PHPUnit\Framework\TestCase protected $observer; /** - * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Customer\Model\Session|\PHPUnit\Framework\MockObject\MockObject */ protected $customerSession; diff --git a/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php index aa3b956e12153..c498ec270dea1 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php @@ -24,7 +24,7 @@ class WishlistSettingsTest extends \PHPUnit\Framework\TestCase private $wishlistSettings; /** - * @var Data|\PHPUnit_Framework_MockObject_MockObject + * @var Data|\PHPUnit\Framework\MockObject\MockObject */ private $helperMock; @@ -46,7 +46,7 @@ protected function setUp() */ public function testAfterGetData() { - /** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $subjectMock */ + /** @var DataProvider|\PHPUnit\Framework\MockObject\MockObject $subjectMock */ $subjectMock = $this->createMock(DataProvider::class); $result = []; $isAllow = true; diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index 23a93bc350203..695ecded081c7 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -8,17 +8,17 @@ class ConfigurableProductTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\Pricing\SaleableInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\SaleableInterface|\PHPUnit\Framework\MockObject\MockObject */ private $saleableItem; /** - * @var \Magento\Framework\Pricing\Adjustment\CalculatorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\Adjustment\CalculatorInterface|\PHPUnit\Framework\MockObject\MockObject */ private $calculator; /** - * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit\Framework\MockObject\MockObject */ private $priceCurrency; @@ -28,7 +28,7 @@ class ConfigurableProductTest extends \PHPUnit\Framework\TestCase private $model; /** - * @var \Magento\Framework\Pricing\PriceInfoInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\PriceInfoInterface|\PHPUnit\Framework\MockObject\MockObject */ private $priceInfoMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/DownloadableTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/DownloadableTest.php index 0623eeabc6554..ed2318274d1c0 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/DownloadableTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/DownloadableTest.php @@ -15,17 +15,17 @@ class DownloadableTest extends \PHPUnit\Framework\TestCase { /** - * @var SaleableInterface|\PHPUnit_Framework_MockObject_MockObject + * @var SaleableInterface|\PHPUnit\Framework\MockObject\MockObject */ private $saleableItem; /** - * @var CalculatorInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CalculatorInterface|\PHPUnit\Framework\MockObject\MockObject */ private $calculator; /** - * @var PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var PriceCurrencyInterface|\PHPUnit\Framework\MockObject\MockObject */ private $priceCurrency; @@ -35,7 +35,7 @@ class DownloadableTest extends \PHPUnit\Framework\TestCase private $model; /** - * @var PriceInfoInterface|\PHPUnit_Framework_MockObject_MockObject + * @var PriceInfoInterface|\PHPUnit\Framework\MockObject\MockObject */ private $priceInfoMock; diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/Render/ConfiguredPriceBoxTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/Render/ConfiguredPriceBoxTest.php index 40291f2420b2e..1ec47db91f194 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/Render/ConfiguredPriceBoxTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/Render/ConfiguredPriceBoxTest.php @@ -10,22 +10,22 @@ class ConfiguredPriceBoxTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Framework\View\Element\Template\Context|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Element\Template\Context|\PHPUnit\Framework\MockObject\MockObject */ private $templateContext; /** - * @var \Magento\Framework\Pricing\SaleableInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\SaleableInterface|\PHPUnit\Framework\MockObject\MockObject */ private $saleableItem; /** - * @var \Magento\Framework\Pricing\Price\PriceInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\Price\PriceInterface|\PHPUnit\Framework\MockObject\MockObject */ private $price; /** - * @var \Magento\Framework\Pricing\Render\RendererPool|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Pricing\Render\RendererPool|\PHPUnit\Framework\MockObject\MockObject */ private $rendererPool; @@ -35,7 +35,7 @@ class ConfiguredPriceBoxTest extends \PHPUnit\Framework\TestCase private $model; /** - * @var \Magento\Catalog\Model\Product\Configuration\Item\ItemInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product\Configuration\Item\ItemInterface|\PHPUnit\Framework\MockObject\MockObject */ private $item; diff --git a/app/design/adminhtml/Magento/backend/Magento_Tax/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Tax/web/css/source/_module.less index f7ae4cb821fff..2377f7c9a9c11 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Tax/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Tax/web/css/source/_module.less @@ -14,7 +14,7 @@ .block.mselect-list.paginated { .admin__action-multiselect-search-wrap { - border:1px solid @color-gray80; + border: 1px solid @color-gray80; border-bottom: none; border-radius: 3px; margin: 0; @@ -25,3 +25,9 @@ font-size: 1.3rem; } } + +.admin__fieldset > .admin__field > .admin__field-control { + input.zip-is-range-checkbox { + margin: 8px 0 0 0; + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less index cd7177d329e7f..f57420deb621d 100644 --- a/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Catalog/web/css/source/_module.less @@ -543,8 +543,8 @@ } .compare, - .product-item-actions .actions-secondary > .action.tocompare, - [class*='block-compare'] { + .product-addto-links .action.tocompare, + .product-item-actions .actions-secondary > .action.tocompare { display: none; } } diff --git a/app/design/frontend/Magento/luma/Magento_AdvancedCheckout/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_AdvancedCheckout/web/css/source/_module.less index 8538a481903c7..4f2cf789d3a0e 100644 --- a/app/design/frontend/Magento/luma/Magento_AdvancedCheckout/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_AdvancedCheckout/web/css/source/_module.less @@ -48,12 +48,6 @@ } .block-content { - &:extend(.abs-add-clearfix-desktop all); - - .box { - &:extend(.abs-blocks-2columns all); - } - .actions-toolbar { clear: both; .lib-actions-toolbar( @@ -188,4 +182,16 @@ &:extend(.abs-add-clearfix-desktop all); } } + + .column { + .block-addbysku { + .block-content { + &:extend(.abs-add-clearfix-desktop all); + + .box { + &:extend(.abs-blocks-2columns all); + } + } + } + } } diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less index e3296c3bcf825..d0b7aa1523ad6 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less @@ -1002,8 +1002,7 @@ } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { - .compare.wrapper, - [class*='block-compare'] { + .compare.wrapper { display: none; } .catalog-product_compare-index { diff --git a/app/design/frontend/Magento/luma/Magento_CatalogSearch/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_CatalogSearch/web/css/source/_module.less index 31859a46d3efe..2176fcd241916 100644 --- a/app/design/frontend/Magento/luma/Magento_CatalogSearch/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_CatalogSearch/web/css/source/_module.less @@ -18,7 +18,7 @@ // _____________________________________________ & when (@media-common = true) { - + .search { .fieldset { .control { @@ -31,7 +31,7 @@ } } } - + .block-search { margin-bottom: 0; @@ -136,8 +136,6 @@ } .form.search.advanced { - &:extend(.abs-forms-general-desktop all); - .fields.range { .field { &:first-child { @@ -275,4 +273,8 @@ .search-autocomplete { margin-top: 0; } + + .form.search.advanced { + &:extend(.abs-forms-general-desktop all); + } } diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less index 530c700cbc395..e89ad3aaf137f 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less @@ -14,7 +14,6 @@ // --------------------------------------------- .opc-estimated-wrapper { - &:extend(.abs-no-display-desktop all); &:extend(.abs-add-clearfix all); .lib-css(background, @checkout-step-content-mobile__background); .lib-css(border-bottom, @checkout-step-title__border); @@ -54,6 +53,6 @@ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .opc-estimated-wrapper { - display: none; + &:extend(.abs-no-display-desktop all); } } diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less index 7b06186ef9ad3..fbd9701d44be9 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/fields/_file-uploader.less @@ -129,7 +129,6 @@ .file-uploader-preview { .action-remove { - &:extend(.abs-action-reset all); .lib-icon-font ( @icon-delete__content, @_icon-font: @icons__font-name, diff --git a/app/design/frontend/Magento/luma/Magento_Downloadable/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Downloadable/web/css/source/_module.less index 7d911220d9dca..40b8cb8740810 100644 --- a/app/design/frontend/Magento/luma/Magento_Downloadable/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Downloadable/web/css/source/_module.less @@ -92,7 +92,6 @@ } .field.choice { - &:extend(.clearer all); border-bottom: 1px solid @color-gray92; box-sizing: border-box; margin-bottom: @indent__s; @@ -178,10 +177,6 @@ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .page-product-downloadable { - .product-add-form { - &:extend(.clearer all); - } - .product-options-wrapper { float: left; width: 55%; diff --git a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less index 0f2a0db56a355..0453937471a28 100644 --- a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less @@ -27,7 +27,6 @@ & when (@media-common = true) { .gift-message { .field { - &:extend(.abs-clearfix all); margin-bottom: @indent__base; .label { diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less index 599218f970907..bab8a2abb9b93 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less @@ -311,7 +311,6 @@ margin-right: 30px; &.print { - &:extend(.abs-action-print all); display: none; margin: 0; } @@ -589,6 +588,7 @@ .order-actions-toolbar { .action.print { + &:extend(.abs-action-print all); display: block; float: right; } @@ -709,7 +709,7 @@ } } -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { .order-links { .item { margin: 0 @tab-control__margin-right 0 0; diff --git a/app/functions.php b/app/functions.php deleted file mode 100644 index 6b3dae71c42c6..0000000000000 --- a/app/functions.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * Create value-object \Magento\Framework\Phrase - * @deprecated The global function __() is now loaded via Magento Framework, the below require is only - * for backwards compatibility reasons and this file will be removed in a future version - * @see Magento\Framework\Phrase\__.php - * @SuppressWarnings(PHPMD.ShortMethodName) - * @return \Magento\Framework\Phrase - */ -if (!function_exists('__')) { - /** - * @return \Magento\Framework\Phrase - */ - function __() - { - $argc = func_get_args(); - - $text = array_shift($argc); - if (!empty($argc) && is_array($argc[0])) { - $argc = $argc[0]; - } - - return new \Magento\Framework\Phrase($text, $argc); - } -} diff --git a/composer.json b/composer.json index 9cbbf1689738f..db34b0a9c2fd0 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "lib-libxml": "*", "braintree/braintree_php": "3.35.0", "colinmollenhour/cache-backend-file": "~1.4.1", - "colinmollenhour/cache-backend-redis": "1.10.6", + "colinmollenhour/cache-backend-redis": "1.11.0", "colinmollenhour/credis": "1.10.0", "colinmollenhour/php-redis-session-abstract": "~1.4.0", "composer/composer": "^1.6", @@ -88,7 +88,7 @@ "friendsofphp/php-cs-fixer": "~2.14.0", "lusitanian/oauth": "~0.8.10", "magento/magento-coding-standard": "*", - "magento/magento2-functional-testing-framework": "2.5.4", + "magento/magento2-functional-testing-framework": "~2.6.3", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index 5b94f60fa80a9..144614ba2279d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "988eebffd81167973e4a51d7efd5be46", + "content-hash": "d9bed7b45c83f9133bdec76acac8b796", "packages": [ { "name": "braintree/braintree_php", @@ -88,16 +88,16 @@ }, { "name": "colinmollenhour/cache-backend-redis", - "version": "1.10.6", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis.git", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf" + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/cc941a5f4cc017e11d3eab9061811ba9583ed6bf", - "reference": "cc941a5f4cc017e11d3eab9061811ba9583ed6bf", + "url": "https://api.github.com/repos/colinmollenhour/Cm_Cache_Backend_Redis/zipball/389fb68de15660e39b055d149d31f3708b5d6cbc", + "reference": "389fb68de15660e39b055d149d31f3708b5d6cbc", "shasum": "" }, "require": { @@ -120,7 +120,7 @@ ], "description": "Zend_Cache backend using Redis with full support for tags.", "homepage": "https://github.com/colinmollenhour/Cm_Cache_Backend_Redis", - "time": "2018-09-24T16:02:07+00:00" + "time": "2019-03-03T04:04:49+00:00" }, { "name": "colinmollenhour/credis", @@ -830,6 +830,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "abandoned": true, "time": "2018-07-31T13:22:33+00:00" }, { @@ -880,6 +881,7 @@ "Guzzle", "stream" ], + "abandoned": true, "time": "2014-10-12T19:18:40+00:00" }, { @@ -1848,6 +1850,11 @@ "MIT" ], "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1855,11 +1862,6 @@ { "name": "Thibaud Fabre", "email": "thibaud@aztech.io" - }, - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" } ], "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", @@ -5197,6 +5199,90 @@ ], "time": "2017-11-03T13:08:21+00:00" }, + { + "name": "aws/aws-sdk-php", + "version": "3.133.8", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd", + "reference": "c564fcccd5fc7b5e8514d1cbe35558be1e3a11cd", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4.1", + "mtdowling/jmespath.php": "^2.5", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2020-02-05T19:12:47+00:00" + }, { "name": "behat/gherkin", "version": "v4.6.0", @@ -6589,67 +6675,6 @@ ], "time": "2019-10-30T14:39:59+00:00" }, - { - "name": "facebook/webdriver", - "version": "1.7.1", - "source": { - "type": "git", - "url": "https://github.com/facebook/php-webdriver.git", - "reference": "e43de70f3c7166169d0f14a374505392734160e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/e43de70f3c7166169d0f14a374505392734160e5", - "reference": "e43de70f3c7166169d0f14a374505392734160e5", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "ext-zip": "*", - "php": "^5.6 || ~7.0", - "symfony/process": "^2.8 || ^3.1 || ^4.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.0", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "php-coveralls/php-coveralls": "^2.0", - "php-mock/php-mock-phpunit": "^1.1", - "phpunit/phpunit": "^5.7", - "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", - "squizlabs/php_codesniffer": "^2.6", - "symfony/var-dumper": "^3.3 || ^4.0" - }, - "suggest": { - "ext-SimpleXML": "For Firefox profile creation" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-community": "1.5-dev" - } - }, - "autoload": { - "psr-4": { - "Facebook\\WebDriver\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "description": "A PHP client for Selenium WebDriver", - "homepage": "https://github.com/facebook/php-webdriver", - "keywords": [ - "facebook", - "php", - "selenium", - "webdriver" - ], - "abandoned": "php-webdriver/webdriver", - "time": "2019-06-13T08:02:18+00:00" - }, { "name": "flow/jsonpath", "version": "0.5.0", @@ -7356,34 +7381,41 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.5.4", + "version": "2.6.3", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "4f482ce22a755a812b76f81020ae71d502f9d043" + "reference": "f1d9f9ede3fea875427f5d1b012561da1dca6206" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/4f482ce22a755a812b76f81020ae71d502f9d043", - "reference": "4f482ce22a755a812b76f81020ae71d502f9d043", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/f1d9f9ede3fea875427f5d1b012561da1dca6206", + "reference": "f1d9f9ede3fea875427f5d1b012561da1dca6206", "shasum": "" }, "require": { "allure-framework/allure-codeception": "~1.3.0", + "aws/aws-sdk-php": "^3.132", "codeception/codeception": "~2.4.5", "composer/composer": "^1.4", "consolidation/robo": "^1.0.0", "csharpru/vault-php": "~3.5.3", "csharpru/vault-php-guzzle6-transport": "^2.0", "ext-curl": "*", + "ext-json": "*", + "ext-openssl": "*", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", "mustache/mustache": "~2.5", "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", + "php-webdriver/webdriver": "^1.8.0", "symfony/process": "^2.8 || ^3.1 || ^4.0", "vlucas/phpdotenv": "^2.4" }, + "replace": { + "facebook/webdriver": "^1.7.1" + }, "require-dev": { "brainmaestro/composer-git-hooks": "^2.3.1", "codacy/coverage": "^1.4", @@ -7430,7 +7462,7 @@ "magento", "testing" ], - "time": "2019-12-12T20:14:00+00:00" + "time": "2020-02-27T19:56:31+00:00" }, { "name": "mikey179/vfsstream", @@ -7478,6 +7510,63 @@ "homepage": "http://vfs.bovigo.org/", "time": "2019-10-30T15:31:00+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "52168cb9472de06979613d365c7f1ab8798be895" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/52168cb9472de06979613d365c7f1ab8798be895", + "reference": "52168cb9472de06979613d365c7f1ab8798be895", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "symfony/polyfill-mbstring": "^1.4" + }, + "require-dev": { + "composer/xdebug-handler": "^1.2", + "phpunit/phpunit": "^4.8.36|^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "time": "2019-12-30T18:03:34+00:00" + }, { "name": "mustache/mustache", "version": "v2.13.0", @@ -7765,6 +7854,71 @@ ], "time": "2018-02-15T16:58:55+00:00" }, + { + "name": "php-webdriver/webdriver", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "3e33ee3b8a688d719c55acdd7c6788e3006e1d3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/3e33ee3b8a688d719c55acdd7c6788e3006e1d3e", + "reference": "3e33ee3b8a688d719c55acdd7c6788e3006e1d3e", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^5.6 || ~7.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^2.8 || ^3.1 || ^4.0 || ^5.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "jakub-onderka/php-parallel-lint": "^1.0", + "php-coveralls/php-coveralls": "^2.0", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "^5.7", + "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", + "sminnee/phpunit-mock-objects": "^3.4", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^3.3 || ^4.0 || ^5.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "files": [ + "lib/Exception/TimeoutException.php" + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", + "homepage": "https://github.com/php-webdriver/php-webdriver", + "keywords": [ + "Chromedriver", + "geckodriver", + "php", + "selenium", + "webdriver" + ], + "time": "2020-02-10T15:04:25+00:00" + }, { "name": "phpcollection/phpcollection", "version": "0.5.0", diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index 76107ebc6a13a..3123295166a35 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -8,19 +8,13 @@ namespace Magento\Catalog\Api; use Magento\Authorization\Model\Role; -use Magento\Authorization\Model\Rules; use Magento\Authorization\Model\RoleFactory; +use Magento\Authorization\Model\Rules; use Magento\Authorization\Model\RulesFactory; use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\Downloadable\Api\DomainManagerInterface; use Magento\Downloadable\Model\Link; -use Magento\Integration\Api\AdminTokenServiceInterface; -use Magento\Store\Model\Store; -use Magento\Store\Model\Website; -use Magento\Store\Model\WebsiteRepository; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\TestCase\WebapiAbstract; use Magento\Framework\Api\ExtensibleDataInterface; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -28,6 +22,12 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; +use Magento\Integration\Api\AdminTokenServiceInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\Website; +use Magento\Store\Model\WebsiteRepository; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; /** * Test for \Magento\Catalog\Api\ProductRepositoryInterface @@ -491,7 +491,6 @@ public function testProductLinks() ProductInterface::TYPE_ID => 'simple', ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, - ProductInterface::TYPE_ID => 'simple', ProductInterface::ATTRIBUTE_SET_ID => 4, ProductInterface::EXTENSION_ATTRIBUTES_KEY => [ 'stock_item' => $this->getStockItemData() @@ -1393,8 +1392,6 @@ public function testTierPrices() $response = $this->getProduct($productData[ProductInterface::SKU]); $response[self::KEY_TIER_PRICES] = []; $response = $this->updateProduct($response); - $this->assertArrayHasKey(self::KEY_TIER_PRICES, $response, "expected to have the 'tier_prices' key"); - $this->assertEmpty($response[self::KEY_TIER_PRICES], "expected to have an empty array of 'tier_prices'"); // delete the product with tier prices; expect that all goes well $response = $this->deleteProduct($productData[ProductInterface::SKU]); @@ -1618,7 +1615,6 @@ public function testUpdateStatus() ProductInterface::TYPE_ID => 'simple', ProductInterface::PRICE => 100, ProductInterface::STATUS => 0, - ProductInterface::TYPE_ID => 'simple', ProductInterface::ATTRIBUTE_SET_ID => 4, ]; diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php index 7a02e2f843719..8ee23a1efea44 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php @@ -8,6 +8,8 @@ use Magento\Customer\Api\Data\CustomerInterface as Customer; use Magento\Customer\Api\Data\AddressInterface as Address; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SortOrder; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\LocalizedException; @@ -482,11 +484,17 @@ public function testCreateCustomerWithoutAddressRequiresException() /** * Test with a single filter + * + * @param bool $subscribeStatus + * @return void + * + * @dataProvider subscriptionDataProvider */ - public function testSearchCustomers() + public function testSearchCustomers(bool $subscribeStatus): void { - $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class); - $customerData = $this->_createCustomer(); + $builder = Bootstrap::getObjectManager()->create(FilterBuilder::class); + $subscribeData = $this->buildSubscriptionData($subscribeStatus); + $customerData = $this->_createCustomer($subscribeData); $filter = $builder ->setField(Customer::EMAIL) ->setValue($customerData[Customer::EMAIL]) @@ -494,13 +502,13 @@ public function testSearchCustomers() $this->searchCriteriaBuilder->addFilters([$filter]); $searchData = $this->dataObjectProcessor->buildOutputDataArray( $this->searchCriteriaBuilder->create(), - \Magento\Framework\Api\SearchCriteriaInterface::class + SearchCriteriaInterface::class ); $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -511,6 +519,35 @@ public function testSearchCustomers() $searchResults = $this->_webApiCall($serviceInfo, $requestData); $this->assertEquals(1, $searchResults['total_count']); $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]); + $this->assertEquals($subscribeStatus, $searchResults['items'][0]['extension_attributes']['is_subscribed']); + } + + /** + * Build subscription extension attributes data + * + * @param bool $status + * @return array + */ + private function buildSubscriptionData(bool $status): array + { + return [ + 'extension_attributes' => [ + 'is_subscribed' => $status, + ], + ]; + } + + /** + * Subscription customer data provider + * + * @return array + */ + public function subscriptionDataProvider(): array + { + return [ + 'subscribed user' => [true], + 'not subscribed user' => [false], + ]; } /** @@ -857,11 +894,12 @@ protected function _getCustomerData($customerId) } /** + * @param array|null $additionalData * @return array|bool|float|int|string */ - protected function _createCustomer() + protected function _createCustomer(?array $additionalData = []) { - $customerData = $this->customerHelper->createSampleCustomer(); + $customerData = $this->customerHelper->createSampleCustomer($additionalData); $this->currentCustomerId[] = $customerData['id']; return $customerData; } 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 b78c8894970b5..0a8d98eefe9e3 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 @@ -163,6 +163,48 @@ public function testMergeTwoCustomerCarts() $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } + /** + * @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 + * @expectedException \Exception + * @expectedExceptionMessage Required parameter "source_cart_id" is missing + */ + public function testMergeCartsWithEmptySourceCartId() + { + $customerQuote = $this->quoteFactory->create(); + $this->quoteResource->load($customerQuote, 'test_quote', 'reserved_order_id'); + + $customerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$customerQuote->getId()); + $guestQuoteMaskedId = ""; + + $query = $this->getCartMergeMutation($guestQuoteMaskedId, $customerQuoteMaskedId); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Required parameter "destination_cart_id" is missing + */ + public function testMergeCartsWithEmptyDestinationCartId() + { + $guestQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $guestQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + + $customerQuoteMaskedId = ""; + $guestQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$guestQuote->getId()); + + $query = $this->getCartMergeMutation($guestQuoteMaskedId, $customerQuoteMaskedId); + $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + } + /** * Add simple product to cart * diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 57aeda3295268..74f8e3c2e37dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -233,6 +233,10 @@ public function testSetDisabledPaymentOnCart() public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array { return [ + 'missed_cart_id' => [ + 'cart_id: "", payment_method: {code: "' . Checkmo::PAYMENT_METHOD_CHECKMO_CODE . '"}', + 'Required parameter "cart_id" is missing.' + ], 'missed_payment_method_code' => [ 'cart_id: "cart_id_value", payment_method: {code: ""}', 'Required parameter "code" for "payment_method" is missing.' diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php index c3e35f0bf80e8..08c7bdd8dbc52 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php @@ -183,6 +183,10 @@ public function testSetPaymentMethodWithoutRequiredParameters(string $input, str public function dataProviderSetPaymentMethodWithoutRequiredParameters(): array { return [ + 'missed_cart_id' => [ + 'cart_id: "", payment_method: {code: "' . Checkmo::PAYMENT_METHOD_CHECKMO_CODE . '"}', + 'Required parameter "cart_id" is missing.' + ], 'missed_payment_method_code' => [ 'cart_id: "cart_id_value", payment_method: {code: ""}', 'Required parameter "code" for "payment_method" is missing.' diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php index afd347cb08e9b..8cccfbe1905a5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php @@ -125,7 +125,6 @@ public function testProductLinks() ProductInterface::TYPE_ID => 'simple', ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, - ProductInterface::TYPE_ID => 'simple', ProductInterface::ATTRIBUTE_SET_ID => 4, ProductInterface::EXTENSION_ATTRIBUTES_KEY => [ 'stock_item' => $this->getStockItemData() diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php index 00c8bb85d9be7..e03a54f9463d7 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php @@ -6,6 +6,8 @@ */ namespace Magento\Quote\Api; +use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\CatalogInventory\Model\Stock; use Magento\TestFramework\TestCase\WebapiAbstract; class GuestCartItemRepositoryTest extends WebapiAbstract @@ -167,9 +169,13 @@ public function testRemoveItem() /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php + * @param array $stockData + * @param string|null $errorMessage + * @dataProvider updateItemDataProvider */ - public function testUpdateItem() + public function testUpdateItem(array $stockData, string $errorMessage = null) { + $this->updateStockData('simple_one', $stockData); /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); $quote->load('test_order_item_with_items', 'reserved_order_id'); @@ -215,6 +221,9 @@ public function testUpdateItem() ], ]; } + if ($errorMessage) { + $this->expectExceptionMessage($errorMessage); + } $this->_webApiCall($serviceInfo, $requestData); $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); $quote->load('test_order_item_with_items', 'reserved_order_id'); @@ -223,4 +232,66 @@ public function testUpdateItem() $this->assertEquals(5, $item->getQty()); $this->assertEquals($itemId, $item->getItemId()); } + + /** + * @return array + */ + public function updateItemDataProvider(): array + { + return [ + [ + [] + ], + [ + [ + 'qty' => 0, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_YES_NOTIFY, + ] + ], + [ + [ + 'qty' => 0, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_NO, + ], + 'This product is out of stock.' + ], + [ + [ + 'qty' => 2, + 'is_in_stock' => 1, + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_NO, + ], + 'The requested qty is not available' + ] + ]; + } + + /** + * Update product stock + * + * @param string $sku + * @param array $stockData + * @return void + */ + private function updateStockData(string $sku, array $stockData): void + { + if ($stockData) { + /** @var $stockRegistry StockRegistryInterface */ + $stockRegistry = $this->objectManager->create(StockRegistryInterface::class); + $stockItem = $stockRegistry->getStockItemBySku($sku); + $stockItem->addData($stockData); + $stockRegistry->updateStockItemBySku($sku, $stockItem); + } + } } diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml index dc02e2424b827..83ab138dacf55 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml @@ -11,7 +11,7 @@ <field name="payment_code" xsi:type="string">braintree</field> <field name="cc_number" xsi:type="string">4000000000000002</field> <field name="cc_exp_month" xsi:type="string">01</field> - <field name="cc_exp_year" xsi:type="string">20</field> + <field name="cc_exp_year" xsi:type="string">24</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -19,7 +19,7 @@ <field name="payment_code" xsi:type="string">braintree</field> <field name="cc_number" xsi:type="string">4000000000000028</field> <field name="cc_exp_month" xsi:type="string">01</field> - <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_exp_year" xsi:type="string">2024</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -27,7 +27,7 @@ <field name="payment_code" xsi:type="string">braintree</field> <field name="cc_number" xsi:type="string">4000111111111511</field> <field name="cc_exp_month" xsi:type="string">01</field> - <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_exp_year" xsi:type="string">2024</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -35,7 +35,7 @@ <field name="payment_code" xsi:type="string">braintree</field> <field name="cc_number" xsi:type="string">4111111111111111</field> <field name="cc_exp_month" xsi:type="string">01 - January</field> - <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_exp_year" xsi:type="string">2024</field> </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml index 5ea1b692e3eb9..3630a642534fb 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/CreateCategoryEntityTest.xml @@ -56,6 +56,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> </variation> <variation name="CreateCategoryEntityTestVariation4_Subcategory_AllFields"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="description" xsi:type="string">Create not anchor subcategory specifying all fields</data> <data name="addCategory" xsi:type="string">addSubcategory</data> <data name="category/data/parent_id/dataset" xsi:type="string">default_category</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml index d6b75e5c3a6e4..ce1e473836ed8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityPartTwoTest.xml @@ -159,6 +159,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertCanSaveProduct" /> </variation> <variation name="CreateSimpleProductNotVisibleIndividually" summary="Check that url rewrite is not generated for product if visibility is 'Not Visible Individually'" ticketId="MAGETWO-53788"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/DeleteCmsPageUrlRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/DeleteCmsPageUrlRewriteEntityTest.xml index ea9d49d662bdd..9a04e3552a137 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/DeleteCmsPageUrlRewriteEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/DeleteCmsPageUrlRewriteEntityTest.xml @@ -8,20 +8,20 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Cms\Test\TestCase\DeleteCmsPageUrlRewriteEntityTest" summary="Delete Cms Page URL Rewrites" ticketId="MAGETWO-25915"> <variation name="DeleteCmsPageUrlRewriteEntityTestVariation1"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="urlRewrite/dataset" xsi:type="string">cms_default_no_redirect</data> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteDeletedMessage" /> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteNotInGrid" /> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertPageByUrlRewriteIsNotFound" /> </variation> <variation name="DeleteCmsPageUrlRewriteEntityTestVariation2"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="urlRewrite/dataset" xsi:type="string">cms_default_permanent_redirect</data> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteDeletedMessage" /> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertPageByUrlRewriteIsNotFound" /> </variation> <variation name="DeleteCmsPageUrlRewriteEntityTestVariation3"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="urlRewrite/dataset" xsi:type="string">cms_default_temporary_redirect</data> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteDeletedMessage" /> <constraint name="Magento\UrlRewrite\Test\Constraint\AssertPageByUrlRewriteIsNotFound" /> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/UpdateCmsPageRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/UpdateCmsPageRewriteEntityTest.xml index 1125ce8d916c1..872a719d54fe9 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/UpdateCmsPageRewriteEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/UpdateCmsPageRewriteEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Cms\Test\TestCase\UpdateCmsPageRewriteEntityTest" summary="Update Cms Page URL Rewrites " ticketId="MAGETWO-26173"> <variation name="UpdateCmsPageRewriteEntityTestVariation1"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="cmsPageRewrite/dataset" xsi:type="string">cms_default_no_redirect</data> <data name="urlRewrite/data/store_id" xsi:type="string">Main Website/Main Website Store/%default%</data> <data name="urlRewrite/data/request_path" xsi:type="string">request_path%isolation%</data> @@ -18,7 +18,7 @@ <constraint name="Magento\Cms\Test\Constraint\AssertUrlRewriteCmsPageRedirect" /> </variation> <variation name="UpdateCmsPageRewriteEntityTestVariation2"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="cmsPageRewrite/dataset" xsi:type="string">cms_default_temporary_redirect</data> <data name="urlRewrite/data/store_id" xsi:type="string">Main Website/Main Website Store/Default Store View</data> <data name="urlRewrite/data/request_path" xsi:type="string">request_path%isolation%.html</data> @@ -28,7 +28,7 @@ <constraint name="Magento\Cms\Test\Constraint\AssertUrlRewriteCmsPageRedirect" /> </variation> <variation name="UpdateCmsPageRewriteEntityTestVariation3"> - <data name="tag" xsi:type="string">severity:S2,mftf_migrated:yes</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="cmsPageRewrite/dataset" xsi:type="string">cms_default_permanent_redirect</data> <data name="urlRewrite/data/store_id" xsi:type="string">Main Website/Main Website Store/Default Store View</data> <data name="urlRewrite/data/request_path" xsi:type="string">request_path%isolation%.htm</data> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCategoryRewriteEntityTest.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCategoryRewriteEntityTest.xml index 1293c6e89b69a..b0f2a9e293295 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCategoryRewriteEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCategoryRewriteEntityTest.xml @@ -39,6 +39,7 @@ <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryRedirect" /> </variation> <variation name="CreateCategoryRewriteEntityTestVariation4" summary="Create Category URL Rewrites with Permanent redirect"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="urlRewrite/data/entity_type" xsi:type="string">For Category</data> <data name="urlRewrite/data/store_id" xsi:type="string">Main Website/Main Website Store/Default Store View</data> <data name="urlRewrite/data/request_path" xsi:type="string">request_path%isolation%</data> diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 1bfc928f2916a..f0ce2e24545eb 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -558,7 +558,7 @@ private function copyAppConfigFiles() } } } - + /** * Copies global configuration file from the tests folder (see TESTS_GLOBAL_CONFIG_FILE) * diff --git a/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php b/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php new file mode 100644 index 0000000000000..6a7d034d5892f --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Bundle\Model; + +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Api\Data\ProductInterface; + +/** + * Prepare bundle product links + */ +class PrepareBundleLinks +{ + /** @var LinkInterfaceFactory */ + private $linkFactory; + + /** @var OptionInterfaceFactory */ + private $optionLinkFactory; + + /** @var ProductExtensionFactory */ + private $extensionAttributesFactory; + + /** + * @param LinkInterfaceFactory $linkFactory + * @param OptionInterfaceFactory $optionLinkFactory + * @param ProductExtensionFactory $extensionAttributesFactory + */ + public function __construct( + LinkInterfaceFactory $linkFactory, + OptionInterfaceFactory $optionLinkFactory, + ProductExtensionFactory $extensionAttributesFactory + ) { + $this->linkFactory = $linkFactory; + $this->optionLinkFactory = $optionLinkFactory; + $this->extensionAttributesFactory = $extensionAttributesFactory; + } + + /** + * Prepare bundle product links + * + * @param ProductInterface $product + * @param array $bundleOptionsData + * @param array $bundleSelectionsData + * @return ProductInterface + */ + public function execute( + ProductInterface $product, + array $bundleOptionsData, + array $bundleSelectionsData + ): ProductInterface { + $product->setBundleOptionsData($bundleOptionsData) + ->setBundleSelectionsData($bundleSelectionsData); + $options = []; + foreach ($product->getBundleOptionsData() as $key => $optionData) { + $option = $this->optionLinkFactory->create(['data' => $optionData]); + $option->setSku($product->getSku()); + $option->setOptionId(null); + $links = []; + $bundleLinks = $product->getBundleSelectionsData(); + foreach ($bundleLinks[$key] as $linkData) { + $link = $this->linkFactory->create(['data' => $linkData]); + $link->setQty($linkData['selection_qty']); + $priceType = $price = null; + if ($product->getPriceType() === Price::PRICE_TYPE_FIXED) { + $priceType = $linkData['selection_price_type'] ?? null; + $price = $linkData['selection_price_value'] ?? null; + } + $link->setPriceType($priceType); + $link->setPrice($price); + $links[] = $link; + } + $option->setProductLinks($links); + $options[] = $option; + } + /** @var ProductExtensionFactory $extensionAttributesFactory */ + $extensionAttributes = $product->getExtensionAttributes() ?? $this->extensionAttributesFactory->create(); + $extensionAttributes->setBundleProductOptions($options); + $product->setExtensionAttributes($extensionAttributes); + + return $product; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php new file mode 100644 index 0000000000000..f1e98cd4ea0bf --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Directory\Model; + +use Magento\Directory\Model\RegionFactory; + +/** + * Return region ID by region default name and country code. + */ +class GetRegionIdByName +{ + /** + * @var RegionFactory + */ + private $regionFactory; + + /** + * @var array + */ + private $regionIdsCache; + + /** + * @param RegionFactory $regionFactory + */ + public function __construct( + RegionFactory $regionFactory + ) { + $this->regionFactory = $regionFactory; + } + + /** + * Get region ID from cache property if region id exist or load it. + * + * @param string $regionName + * @param string $countryId + * @return int|null + */ + public function execute(string $regionName, string $countryId): ?int + { + $cacheKey = "{$regionName}_{$countryId}"; + + if (!isset($this->regionIdsCache[$cacheKey])) { + $region = $this->regionFactory->create()->loadByName($regionName, $countryId); + $this->regionIdsCache[$cacheKey] = $region->getRegionId() ? (int)$region->getRegionId() : null; + } + + return $this->regionIdsCache[$cacheKey]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php new file mode 100644 index 0000000000000..1ac68b8d7ff57 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Backend\Block\Dashboard\Tab; + +use Magento\Backend\Block\Dashboard\Graph; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Test for \Magento\Backend\Block\Dashboard\Tab\Orders class. + * + * @magentoAppArea adminhtml + */ +class OrdersTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var LayoutInterface + */ + private $layout; + + /** + * @var Graph + */ + private $graphBlock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->graphBlock = $this->layout->createBlock(Graph::class); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order_list_with_invoice.php + * @dataProvider chartUrlDataProvider + * @param string $period + * @param string $expectedAxisRange + * @return void + */ + public function testGetChartUrl(string $period, string $expectedAxisRange): void + { + $this->graphBlock->getRequest()->setParams(['period' => $period]); + $ordersBlock = $this->layout->createBlock(Orders::class); + $decodedChartUrl = urldecode($ordersBlock->getChartUrl()); + $this->assertEquals($expectedAxisRange, $this->getUrlParamData($decodedChartUrl, 'chxr')); + } + + /** + * @return array + */ + public function chartUrlDataProvider(): array + { + return [ + 'Last 24 Hours' => ['24h', '1,0,2,1'], + 'Last 7 Days' => ['7d', '1,0,3,1'], + 'Current Month' => ['1m', '1,0,3,1'], + 'YTD' => ['1y', '1,0,4,1'], + '2YTD' => ['2y', '1,0,4,1'], + ]; + } + + /** + * @param string $chartUrl + * @param string $paramName + * @return string + */ + private function getUrlParamData(string $chartUrl, string $paramName): string + { + $chartUrlSegments = explode('&', $chartUrl); + foreach ($chartUrlSegments as $chartUrlSegment) { + [$paramKey, $paramValue] = explode('=', $chartUrlSegment); + if ($paramKey === $paramName) { + return $paramValue; + } + } + + return ''; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Braintree/PaymentInformationManagementTest.php b/dev/tests/integration/testsuite/Magento/Braintree/PaymentInformationManagementTest.php new file mode 100644 index 0000000000000..37169e3161407 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Braintree/PaymentInformationManagementTest.php @@ -0,0 +1,314 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Braintree; + +use Braintree\Result\Error; +use Braintree\Result\Successful; +use Braintree\Transaction; +use Braintree\Transaction\CreditCardDetails; +use Magento\Braintree\Gateway\Http\Client\TransactionSale; +use Magento\Braintree\Model\Ui\ConfigProvider; +use Magento\Checkout\Api\PaymentInformationManagementInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\State; +use Magento\Framework\App\Area; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\PaymentInterface; +use Magento\Sales\Api\Data\TransactionInterface; +use Magento\Sales\Api\TransactionRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class PaymentInformationManagementTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var TransactionSale|MockObject + */ + private $client; + + /** + * @var PaymentInformationManagementInterface + */ + private $management; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->client = $this->getMockBuilder(TransactionSale::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManager->addSharedInstance($this->client, TransactionSale::class); + $this->management = $this->objectManager->get(PaymentInformationManagementInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->objectManager->removeSharedInstance(TransactionSale::class); + parent::tearDown(); + } + + /** + * Checks a case when payment method triggers an error during place order flow and + * error messages from payment gateway should be mapped. + * Error messages might be specific for different areas. + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Checkout/_files/quote_with_shipping_method.php + * @magentoConfigFixture current_store payment/braintree/active 1 + * @dataProvider getErrorPerAreaDataProvider + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @param string $area + * @param array $testErrorCodes + * @param string $expectedOutput + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function testSavePaymentInformationAndPlaceOrderWithErrors( + string $area, + array $testErrorCodes, + string $expectedOutput + ) { + /** @var State $state */ + $state = $this->objectManager->get(State::class); + $state->setAreaCode($area); + + $quote = $this->getQuote('test_order_1'); + $payment = $this->getPayment(); + + $errors = ['errors' => []]; + + foreach ($testErrorCodes as $testErrorCode) { + array_push($errors['errors'], ['code' => $testErrorCode]); + } + + $response = new Error(['errors' => $errors, 'transaction' => ['status' => 'declined']]); + + $this->client->method('placeRequest') + ->willReturn(['object' => $response]); + + $this->expectExceptionMessage($expectedOutput); + + $this->management->savePaymentInformationAndPlaceOrder( + $quote->getId(), + $payment + ); + } + + /** + * Gets list of areas with specific error messages. + * + * @return array + */ + public function getErrorPerAreaDataProvider() + { + $testErrorGlobal = ['code' => 81802, 'message' => 'Company is too long.']; + $testErrorAdmin = ['code' => 91511, 'message' => 'Customer does not have any credit cards.']; + $testErrorFake = ['code' => 'fake_code', 'message' => 'Error message should not be mapped.']; + + return [ + [ + Area::AREA_FRONTEND, + [$testErrorAdmin['code'], $testErrorFake['code']], + 'Transaction has been declined. Please try again later.' + ], [ + Area::AREA_FRONTEND, + [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']], + $testErrorGlobal['message'] + ], [ + Area::AREA_ADMINHTML, + [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']], + $testErrorGlobal['message'] . PHP_EOL . $testErrorAdmin['message'] + ], + ]; + } + + /** + * Checks a case when order should be placed with "Sale" payment action. + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Checkout/_files/quote_with_shipping_method.php + * @magentoConfigFixture current_store payment/braintree/active 1 + * @magentoConfigFixture current_store payment/braintree/payment_action authorize_capture + */ + public function testPlaceOrderWithSaleAction() + { + $response = $this->getSuccessfulResponse(Transaction::SUBMITTED_FOR_SETTLEMENT); + $this->client->method('placeRequest') + ->willReturn($response); + + $quote = $this->getQuote('test_order_1'); + $payment = $this->getPayment(); + + $orderId = $this->management->savePaymentInformationAndPlaceOrder($quote->getId(), $payment); + self::assertNotEmpty($orderId); + + $transactions = $this->getPaymentTransactionList((int) $orderId); + self::assertEquals(1, sizeof($transactions), 'Only one transaction should be present.'); + + /** @var TransactionInterface $transaction */ + $transaction = array_pop($transactions); + self::assertEquals( + 'capture', + $transaction->getTxnType(), + 'Order should contain only the "capture" transaction.' + ); + self::assertFalse((bool) $transaction->getIsClosed(), 'Transaction should not be closed.'); + } + + /** + * Checks a case when order should be placed with "Authorize" payment action. + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Checkout/_files/quote_with_shipping_method.php + * @magentoConfigFixture current_store payment/braintree/active 1 + * @magentoConfigFixture current_store payment/braintree/payment_action authorize + */ + public function testPlaceOrderWithAuthorizeAction() + { + $response = $this->getSuccessfulResponse(Transaction::AUTHORIZED); + $this->client->method('placeRequest') + ->willReturn($response); + + $quote = $this->getQuote('test_order_1'); + $payment = $this->getPayment(); + + $orderId = $this->management->savePaymentInformationAndPlaceOrder($quote->getId(), $payment); + self::assertNotEmpty($orderId); + + $transactions = $this->getPaymentTransactionList((int) $orderId); + self::assertEquals(1, sizeof($transactions), 'Only one transaction should be present.'); + + /** @var TransactionInterface $transaction */ + $transaction = array_pop($transactions); + self::assertEquals( + 'authorization', + $transaction->getTxnType(), + 'Order should contain only the "authorization" transaction.' + ); + self::assertFalse((bool) $transaction->getIsClosed(), 'Transaction should not be closed.'); + } + + /** + * Retrieves quote by provided order ID. + * + * @param string $reservedOrderId + * @return CartInterface + */ + private function getQuote(string $reservedOrderId): CartInterface + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId) + ->create(); + + /** @var CartRepositoryInterface $quoteRepository */ + $quoteRepository = $this->objectManager->get(CartRepositoryInterface::class); + $items = $quoteRepository->getList($searchCriteria) + ->getItems(); + + return array_pop($items); + } + + /** + * Creates Braintree payment method. + * + * @return PaymentInterface + */ + private function getPayment(): PaymentInterface + { + /** @var PaymentInterface $payment */ + $payment = $this->objectManager->create(PaymentInterface::class); + $payment->setMethod(ConfigProvider::CODE); + + return $payment; + } + + /** + * Get list of order transactions. + * + * @param int $orderId + * @return TransactionInterface[] + */ + private function getPaymentTransactionList(int $orderId): array + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('order_id', $orderId) + ->create(); + + /** @var TransactionRepositoryInterface $transactionRepository */ + $transactionRepository = $this->objectManager->get(TransactionRepositoryInterface::class); + return $transactionRepository->getList($searchCriteria) + ->getItems(); + } + + /** + * Returns successful Braintree response. + * + * @param string $transactionStatus + * @return array + */ + private function getSuccessfulResponse(string $transactionStatus): array + { + $successResponse = new Successful(); + $successResponse->success = true; + $successResponse->transaction = $this->getBraintreeTransaction($transactionStatus); + + $response = [ + 'object' => $successResponse, + ]; + + return $response; + } + + /** + * Returns Braintree transaction. + * + * @param string $transactionStatus + * @return Transaction + */ + private function getBraintreeTransaction(string $transactionStatus) + { + $cardData = [ + 'token' => '73nrjn', + 'bin' => '411111', + 'cardType' => 'Visa', + 'expirationMonth' => '12', + 'expirationYear' => '2025', + 'last4' => '1111' + ]; + + $transactionData = [ + 'id' => 'c0n6gvjb', + 'status' => $transactionStatus, + 'creditCard' => $cardData, + 'creditCardDetails' => new CreditCardDetails($cardData) + ]; + + $transaction = Transaction::factory($transactionData); + + return $transaction; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php new file mode 100644 index 0000000000000..287a3f07d1964 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php @@ -0,0 +1,194 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\Result\PageFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class consist of basic logic for bundle options view + */ +abstract class AbstractBundleOptionsViewTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var SerializerInterface */ + private $serializer; + + /** @var Registry */ + private $registry; + + /** @var PageFactory */ + private $pageFactory; + + /** @var ProductResource */ + private $productResource; + + /** @var string */ + private $selectLabelXpath = "//fieldset[contains(@class, 'fieldset-bundle-options')]" + . "//label/span[normalize-space(text()) = '%s']"; + + /** @var string */ + private $backToProductDetailButtonXpath = "//button[contains(@class, 'back customization')]"; + + /** @var string */ + private $titleXpath = "//fieldset[contains(@class, 'bundle-options')]//span[contains(text(), 'Customize %s')]"; + + /** @var string */ + private $singleOptionXpath = "//input[contains(@class, 'bundle-option') and contains(@type, 'hidden')]"; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->serializer = $this->objectManager->get(SerializerInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->pageFactory = $this->objectManager->get(PageFactory::class); + $this->productResource = $this->objectManager->get(ProductResource::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + $this->registry->unregister('current_product'); + + parent::tearDown(); + } + + /** + * Process bundle options view with few selections + * + * @param string $sku + * @param string $optionsSelectLabel + * @param array $expectedSelectionsNames + * @param bool $requiredOption + * @return void + */ + protected function processMultiSelectionsView( + string $sku, + string $optionsSelectLabel, + array $expectedSelectionsNames, + bool $requiredOption = false + ): void { + $product = $this->productRepository->get($sku); + $result = $this->renderProductOptionsBlock($product); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->backToProductDetailButtonXpath, $result), + "'Back to product details' button doesn't exist on the page" + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->selectLabelXpath, $optionsSelectLabel), $result), + 'Options select label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->titleXpath, $product->getName()), $result), + sprintf('Customize %s label does not exist on the page', $product->getName()) + ); + $selectPath = $requiredOption ? $this->getRequiredSelectXpath() : $this->getNotRequiredSelectXpath(); + foreach ($expectedSelectionsNames as $selection) { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($selectPath, $selection), $result), + sprintf('Option for product named %s does not exist on the page', $selection) + ); + } + } + + /** + * Process bundle options view with single selection + * + * @param string $sku + * @param string $optionsSelectLabel + * @return void + */ + protected function processSingleSelectionView(string $sku, string $optionsSelectLabel): void + { + $product = $this->productRepository->get($sku); + $result = $this->renderProductOptionsBlock($product); + $this->assertEquals(1, Xpath::getElementsCountForXpath($this->backToProductDetailButtonXpath, $result)); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf($this->selectLabelXpath, $optionsSelectLabel), $result), + 'Options select label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->singleOptionXpath, $result), + 'Bundle product options select with single option does not display correctly' + ); + } + + /** + * Register product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->unregister('current_product'); + $this->registry->register('product', $product); + $this->registry->register('current_product', $product); + } + + /** + * Render bundle product options block + * + * @param ProductInterface $product + * @return string + */ + private function renderProductOptionsBlock(ProductInterface $product): string + { + $this->registerProduct($product); + $page = $this->pageFactory->create(); + $page->addHandle(['default', 'catalog_product_view', 'catalog_product_view_type_bundle']); + $page->getLayout()->generateXml(); + $block = $page->getLayout()->getBlock('product.info.bundle.options'); + + return $block->toHtml(); + } + + /** + * Get required select Xpath + * + * @return string + */ + abstract protected function getRequiredSelectXpath(): string; + + /** + * Get not required select Xpath + * + * @return string + */ + abstract protected function getNotRequiredSelectXpath(): string; +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php new file mode 100644 index 0000000000000..2a61a252e9313 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php @@ -0,0 +1,172 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Check bundle product prices. + * + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + * @magentoAppArea frontend + */ +class BundleProductPriceTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Registry */ + private $registry; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var SerializerInterface */ + private $json; + + /** @var Bundle */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Bundle::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php + * + * @return void + */ + public function testDynamicBundleOptionPrices(): void + { + $expectedData = [ + 'options_prices' => [ + [ + 'oldPrice' => ['amount' => 10], + 'basePrice' => ['amount' => 10], + 'finalPrice' => ['amount' => 10], + ], + [ + 'oldPrice' => ['amount' => 20], + 'basePrice' => ['amount' => 20], + 'finalPrice' => ['amount' => 20], + ], + [ + 'oldPrice' => ['amount' => 30], + 'basePrice' => ['amount' => 30], + 'finalPrice' => ['amount' => 30], + ], + ], + 'bundle_prices' => [ + 'oldPrice' => ['amount' => 0], + 'basePrice' => ['amount' => 0], + 'finalPrice' => ['amount' => 0], + ] + ]; + $this->processBundlePriceView('bundle_product', $expectedData); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product_with_multiple_options_1.php + * + * @return void + */ + public function testFixedBundleOptionPrices(): void + { + $expectedData = [ + 'options_prices' => [ + [ + 'oldPrice' => ['amount' => 2.75], + 'basePrice' => ['amount' => 2.75], + 'finalPrice' => ['amount' => 2.75], + ], + [ + 'oldPrice' => ['amount' => 6.75], + 'basePrice' => ['amount' => 6.75], + 'finalPrice' => ['amount' => 6.75], + ], + ], + 'bundle_prices' => [ + 'oldPrice' => ['amount' => 12.75], + 'basePrice' => ['amount' => 10], + 'finalPrice' => ['amount' => 10], + ] + ]; + $this->processBundlePriceView('bundle-product', $expectedData); + } + + /** + * @param string $productSku + * @param array $expectedData + * @return void + */ + private function processBundlePriceView(string $productSku, array $expectedData): void + { + $this->registerProduct($productSku); + $jsonConfig = $this->json->unserialize($this->block->getJsonConfig()); + $this->assertEquals($expectedData['bundle_prices'], $jsonConfig['prices']); + $this->assertOptionsConfig($expectedData['options_prices'], $jsonConfig); + } + + /** + * Assert options prices. + * + * @param array $expectedData + * @param array $actualData + * @return void + */ + private function assertOptionsConfig(array $expectedData, array $actualData): void + { + $optionConfig = $actualData['options'] ?? null; + $this->assertNotNull($optionConfig); + $optionConfig = reset($optionConfig); + foreach (array_values($optionConfig['selections']) as $key => $selection) { + $this->assertEquals($expectedData[$key], $selection['prices']); + } + } + + /** + * Register the product. + * + * @param string $productSku + * @return void + */ + private function registerProduct(string $productSku): void + { + $product = $this->productRepository->get($productSku); + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php index ce324ed774dc4..dab699064c4bb 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleTest.php @@ -7,53 +7,66 @@ namespace Magento\Bundle\Block\Catalog\Product\View\Type; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + /** - * Test for Magento\Bundle\Block\Catalog\Product\View\Type\Bundle + * Class checks bundle product view behaviour * * @magentoDataFixture Magento/Bundle/_files/product.php - * @magentoDbIsolation disabled + * @magentoDbIsolation enabled * @magentoAppArea frontend + * @see \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle */ -class BundleTest extends \PHPUnit\Framework\TestCase +class BundleTest extends TestCase { - /** - * @var \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle - */ + /** @var Bundle */ private $block; - /** - * @var \Magento\Catalog\Api\Data\ProductInterface - */ - private $product; - - /** - * @var \Magento\TestFramework\ObjectManager - */ + /** @var ObjectManagerInterface */ private $objectManager; - /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface - */ + /** @var ProductRepositoryInterface */ private $productRepository; + /** @var LayoutInterface */ + private $layout; + + /** @var SerializerInterface */ + private $json; + + /** @var Registry */ + private $registry; + /** * @inheritdoc */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - - $this->productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $this->product = $this->productRepository->get('bundle-product', false, null, true); - $this->product->setPriceType(\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC)->save(); - $this->objectManager->get(\Magento\Framework\Registry::class)->unregister('product'); - $this->objectManager->get(\Magento\Framework\Registry::class)->register('product', $this->product); - - $this->block = $this->objectManager->get( - \Magento\Framework\View\LayoutInterface::class - )->createBlock( - \Magento\Bundle\Block\Catalog\Product\View\Type\Bundle::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Bundle::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); } /** @@ -61,12 +74,12 @@ protected function setUp() * * @return void */ - public function testGetJsonConfig() + public function testGetJsonConfig(): void { - $option = $this->productRepository->get('simple'); - $option->setSpecialPrice(5) - ->save(); - $config = json_decode($this->block->getJsonConfig(), true); + $product = $this->updateProduct('bundle-product', ['price_type' => Price::PRICE_TYPE_DYNAMIC]); + $this->registerProduct($product); + $this->updateProduct('simple', ['special_price' => 5]); + $config = $this->json->unserialize($this->block->getJsonConfig()); $options = current($config['options']); $selection = current($options['selections']); $this->assertEquals(10, $selection['prices']['oldPrice']['amount']); @@ -75,10 +88,124 @@ public function testGetJsonConfig() } /** - * Tear Down + * @dataProvider isSalableForStockStatusProvider + * + * @param bool $isSalable + * @param string $expectedValue + * @return void */ - protected function tearDown() + public function testStockStatusView(bool $isSalable, string $expectedValue): void { - $this->objectManager->get(\Magento\Framework\Registry::class)->unregister('product'); + $product = $this->productRepository->get('bundle-product'); + $product->setAllItemsSalable($isSalable); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/type/bundle.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEquals($expectedValue, trim(strip_tags($result))); + } + + /** + * @return array + */ + public function isSalableForStockStatusProvider(): array + { + return [ + 'is_salable' => [ + 'is_salable' => true, + 'expected_value' => 'In stock', + ], + 'is_not_salable' => [ + 'is_salable' => false, + 'expected_value' => 'Out of stock', + ], + ]; + } + + /** + * @dataProvider isSalableForCustomizeButtonProvider + * + * @param bool $isSalable + * @param string $expectedValue + * @return void + */ + public function testCustomizeButton(bool $isSalable, string $expectedValue): void + { + $product = $this->productRepository->get('bundle-product'); + $product->setSalable($isSalable); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/customize.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEquals($expectedValue, trim(strip_tags($result))); + } + + /** + * @return array + */ + public function isSalableForCustomizeButtonProvider(): array + { + return [ + 'is_salable' => [ + 'is_salable' => true, + 'expected_value' => 'Customize and Add to Cart', + ], + 'is_not_salable' => [ + 'is_salable' => false, + 'expected_value' => '', + ], + ]; + } + + /** + * @magentoDataFixture Magento/Bundle/_files/empty_bundle_product.php + * + * @param bool $isSalable + * @param string $expectedValue + * @return void + */ + public function testCustomizeButtonProductWithoutOptions(): void + { + $product = $this->productRepository->get('bundle-product'); + $product->setSalable(true); + $this->block->setTemplate('Magento_Bundle::catalog/product/view/customize.phtml'); + $result = $this->renderBlockHtml($product); + $this->assertEmpty(trim(strip_tags($result))); + } + + /** + * Update product + * + * @param ProductInterface|string $productSku + * @param array $data + * @return ProductInterface + */ + private function updateProduct(string $productSku, array $data): ProductInterface + { + $product = $this->productRepository->get($productSku); + $product->addData($data); + + return $this->productRepository->save($product); + } + + /** + * Register product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } + + /** + * Render block output + * + * @param ProductInterface $product + * @return string + */ + private function renderBlockHtml(ProductInterface $product): string + { + $this->registerProduct($product); + + return $this->block->toHtml(); } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php new file mode 100644 index 0000000000000..cbe150b9fb3f5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks checkbox bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class CheckboxOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-checkbox-options', + 'Checkbox Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-checkbox-required-options', + 'Checkbox Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_checkbox_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-checkbox-required-option', 'Checkbox Options'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//input[@type='checkbox' and contains(@data-validate, 'validate-one-required-by-name')" + . "and contains(@class, 'bundle-option')]/../label//span[normalize-space(text()) = '1 x %s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//input[@type='checkbox' and not(contains(@data-validate, 'validate-one-required-by-name'))" + . "and contains(@class, 'bundle-option')]/../label//span[normalize-space(text()) = '1 x %s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php new file mode 100644 index 0000000000000..128fbe56185f3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks dropdown bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class DropDownOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_dropdown_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-dropdown-options', + 'Dropdown Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_dropdown_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-dropdown-required-options', + 'Dropdown Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/product.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product', 'Bundle Product Items'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and contains(@data-validate, 'required:true')]" + . "/option/span[normalize-space(text()) = '%s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and not(contains(@data-validate, 'required:true'))]" + . "/option/span[normalize-space(text()) = '%s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php new file mode 100644 index 0000000000000..234981f36fa94 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks multiselect bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class MultiselectOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-multiselect-options', + 'Multiselect Options', + $expectedSelectionsNames + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-multiselect-required-options', + 'Multiselect Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_multiselect_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-multiselect-required-option', 'Multiselect Options'); + } + + /** + * @inheridoc + */ + protected function getRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and @multiple='multiple' " + . "and contains(@data-validate, 'required:true')]/option/span[normalize-space(text()) = '1 x %s']"; + } + + /** + * @inheridoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//select[contains(@id, 'bundle-option') and @multiple='multiple'" + . "and not(contains(@data-validate, 'required:true'))]/option/span[normalize-space(text()) = '1 x %s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php new file mode 100644 index 0000000000000..b58f5f7d4189e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Block\Catalog\Product\View\Type; + +/** + * Class checks radio buttons bundle options appearance + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class RadioOptionViewTest extends AbstractBundleOptionsViewTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_options.php + * + * @return void + */ + public function testNotRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView('bundle-product-radio-options', 'Radio Options', $expectedSelectionsNames); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_required_options.php + * + * @return void + */ + public function testRequiredSelectMultiSelectionsView(): void + { + $expectedSelectionsNames = ['Simple Product', 'Simple Product2']; + $this->processMultiSelectionsView( + 'bundle-product-radio-required-options', + 'Radio Options', + $expectedSelectionsNames, + true + ); + } + + /** + * @magentoDataFixture Magento/Bundle/_files/bundle_product_radio_required_option.php + * + * @return void + */ + public function testShowSingle(): void + { + $this->processSingleSelectionView('bundle-product-radio-required-option', 'Radio Options'); + } + + /** + * @inheritdoc + */ + protected function getRequiredSelectXpath(): string + { + return "//input[@type='radio' and contains(@data-validate, 'validate-one-required-by-name')" + . "and contains(@class, 'bundle option')]/../label//span[normalize-space(text()) = '%s']"; + } + + /** + * @inheritdoc + */ + protected function getNotRequiredSelectXpath(): string + { + return "//input[@type='radio' and not(contains(@data-validate, 'validate-one-required-by-name'))" + . "and contains(@class, 'bundle option')]/../label//span[normalize-space(text()) = '%s']"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/PriceTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/PriceTest.php index 4a5757aae3134..b9ffbcf4549ea 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/PriceTest.php @@ -3,68 +3,106 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Bundle\Model\Product; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\Data\TierPriceInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Model\Group; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Catalog\Model\GetCategoryByName; +use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + /** * Class to test bundle prices + * + * @magentoDbIsolation disabled + * @magentoAppIsolation enabled + * @magentoAppArea frontend + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class PriceTest extends \PHPUnit\Framework\TestCase +class PriceTest extends TestCase { + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var GetPriceIndexDataByProductId */ + private $getPriceIndexDataByProductId; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** @var Price */ + private $priceModel; + + /** @var SerializerInterface */ + private $json; + + /** @var GetCategoryByName */ + private $getCategoryByName; + /** - * @var \Magento\Bundle\Model\Product\Price + * @inheritdoc */ - protected $_model; - protected function setUp() { - $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Bundle\Model\Product\Price::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->priceModel = $this->objectManager->get(Price::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->getPriceIndexDataByProductId = $this->objectManager->get(GetPriceIndexDataByProductId::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + $this->getCategoryByName = $this->objectManager->get(GetCategoryByName::class); } /** * @magentoDataFixture Magento/Bundle/_files/product_with_tier_pricing.php + * + * @return void */ - public function testGetTierPrice() + public function testGetTierPrice(): void { - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $product = $productRepository->get('bundle-product'); - // fixture - + $product = $this->productRepository->get('bundle-product'); // Note that this is really not the "tier price" but the "tier discount percentage" // so it is expected to be increasing instead of decreasing - $this->assertEquals(8.0, $this->_model->getTierPrice(2, $product)); - $this->assertEquals(20.0, $this->_model->getTierPrice(3, $product)); - $this->assertEquals(20.0, $this->_model->getTierPrice(4, $product)); - $this->assertEquals(30.0, $this->_model->getTierPrice(5, $product)); + $this->assertEquals(8.0, $this->priceModel->getTierPrice(2, $product)); + $this->assertEquals(20.0, $this->priceModel->getTierPrice(3, $product)); + $this->assertEquals(20.0, $this->priceModel->getTierPrice(4, $product)); + $this->assertEquals(30.0, $this->priceModel->getTierPrice(5, $product)); } /** * Test calculation final price for bundle product with tire price in simple product + * @magentoDataFixture Magento/Bundle/_files/product_with_simple_tier_pricing.php + * @dataProvider getSelectionFinalTotalPriceWithSimpleTierPriceDataProvider * * @param float $bundleQty * @param float $selectionQty * @param float $finalPrice - * @magentoDataFixture Magento/Bundle/_files/product_with_simple_tier_pricing.php - * @dataProvider getSelectionFinalTotalPriceWithSimpleTierPriceDataProvider + * @return void */ public function testGetSelectionFinalTotalPriceWithSimpleTierPrice( float $bundleQty, float $selectionQty, float $finalPrice - ) { - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $bundleProduct = $productRepository->get('bundle-product'); - $simpleProduct = $productRepository->get('simple'); - $simpleProduct->setCustomerGroupId(\Magento\Customer\Model\Group::CUST_GROUP_ALL); + ): void { + $bundleProduct = $this->productRepository->get('bundle-product'); + $simpleProduct = $this->productRepository->get('simple'); + $simpleProduct->setCustomerGroupId(Group::CUST_GROUP_ALL); $this->assertEquals( $finalPrice, - $this->_model->getSelectionFinalTotalPrice( + $this->priceModel->getSelectionFinalTotalPrice( $bundleProduct, $simpleProduct, $bundleQty, @@ -86,4 +124,435 @@ public function getSelectionFinalTotalPriceWithSimpleTierPriceDataProvider(): ar [5, 1, 5], ]; } + + /** + * Fixed Bundle Product with catalog price rule + * @magentoDataFixture Magento/Bundle/_files/fixed_bundle_product_without_discounts.php + * @magentoDataFixture Magento/CatalogRule/_files/rule_apply_as_percentage_of_original_not_logged_user.php + * + * @return void + */ + public function testFixedBundleProductPriceWithCatalogRule(): void + { + $this->checkBundlePrices( + 'fixed_bundle_product_without_discounts', + ['price' => 50, 'final_price' => 45, 'min_price' => 45, 'max_price' => 75, 'tier_price' => null], + ['simple1' => 55, 'simple2' => 56.25, 'simple3' => 70] + ); + } + + /** + * Fixed Bundle Product without discounts + * @magentoDataFixture Magento/Bundle/_files/fixed_bundle_product_without_discounts.php + * + * @return void + */ + public function testFixedBundleProductPriceWithoutDiscounts(): void + { + $this->checkBundlePrices( + 'fixed_bundle_product_without_discounts', + ['price' => 50, 'final_price' => 50, 'min_price' => 60, 'max_price' => 75, 'tier_price' => null], + ['simple1' => 60, 'simple2' => 62.5, 'simple3' => 75] + ); + } + + /** + * Fixed Bundle Product with special price + * @magentoDataFixture Magento/Bundle/_files/fixed_bundle_product_with_special_price.php + * + * @return void + */ + public function testFixedBundleProductPriceWithSpecialPrice(): void + { + $this->checkBundlePrices( + 'fixed_bundle_product_with_special_price', + ['price' => 50, 'final_price' => 40, 'min_price' => 48, 'max_price' => 60, 'tier_price' => null], + ['simple1' => 48, 'simple2' => 50, 'simple3' => 60] + ); + } + + /** + * Fixed Bundle Product with tier price + * @magentoDataFixture Magento/Bundle/_files/fixed_bundle_product_with_tier_price.php + * + * @return void + */ + public function testFixedBundleProductPriceWithTierPrice(): void + { + $this->checkBundlePrices( + 'fixed_bundle_product_with_tier_price', + ['price' => 50, 'final_price' => 50, 'min_price' => 60, 'max_price' => 75, 'tier_price' => 60], + ['simple1' => 45, 'simple2' => 46.88, 'simple3' => 56.25] + ); + } + + /** + * Dynamic Bundle Product without discount + options without discounts + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php + * + * @return void + */ + public function testDynamicBundleProductWithoutDiscountAndOptionsWithoutDiscounts(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_without_discounts', + ['price' => 0, 'final_price' => 0, 'min_price' => 10, 'max_price' => 20, 'tier_price' => null], + ['simple1000' => 10, 'simple1001' => 20] + ); + } + + /** + * Dynamic Bundle Product without discount + options with special price + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php + * + * @return void + */ + public function testDynamicBundleProductWithoutDiscountsAndOptionsWithSpecialPrices(): void + { + $this->updateProducts($this->specialPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_without_discounts', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 15, 'tier_price' => null], + ['simple1000' => 8, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product without discount + options with tier prices + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php + * + * @return void + */ + public function testDynamicBundleProductWithoutDiscountsAndOptionsWithTierPrices(): void + { + $this->updateProducts($this->tierPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_without_discounts', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 17, 'tier_price' => null], + ['simple1000' => 8, 'simple1001' => 17] + ); + } + + /** + * Dynamic Bundle Product without discounts + options with catalog rule + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php + * @magentoDataFixture Magento/CatalogRule/_files/catalog_rule_for_category_999.php + * + * @return void + */ + public function testDynamicBundleProductWithoutDiscountsAndOptionsWithCatalogPriceRule(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_without_discounts', + ['price' => 0, 'final_price' => 0, 'min_price' => 7.5, 'max_price' => 15, 'tier_price' => null], + ['simple1000' => 7.5, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product with tier price + options without discounts + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php + * + * @return void + */ + public function testDynamicBundleProductWithTierPriceAndOptionsWithoutDiscounts(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_tier_price', + ['price' => 0,'final_price' => 0, 'min_price' => 10, 'max_price' => 20, 'tier_price' => 10], + ['simple1000' => 7.5, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product with tier price + options with special prices + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php + * + * @return void + */ + public function testDynamicBundleProductWithTierPriceAndOptionsWithSpecialPrices(): void + { + $this->updateProducts($this->specialPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_tier_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 15, 'tier_price' => 8], + ['simple1000' => 6, 'simple1001' => 11.25] + ); + } + + /** + * Dynamic Bundle Product with tier price + options with tier price + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php + * + * @return void + */ + public function testDynamicBundleProductWithTierPriceAndOptionsWithTierPrices(): void + { + $this->updateProducts($this->tierPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_tier_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 17, 'tier_price' => 8], + ['simple1000' => 6, 'simple1001' => 12.75] + ); + } + + /** + * Dynamic Bundle Product with tier price + options with catalog rule + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php + * @magentoDataFixture Magento/CatalogRule/_files/catalog_rule_for_category_999.php + * + * @return void + */ + public function testDynamicBundleProductWithTierPriceAndOptionsWithCatalogPriceRule(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_tier_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 7.5, 'max_price' => 15, 'tier_price' => 7.5], + ['simple1000' => 5.63, 'simple1001' => 11.25] + ); + } + + /** + * Dynamic Bundle Product with special price + options without discounts + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php + * + * @return void + */ + public function testDynamicBundleProductWithSpecialPriceAndOptionsWithoutDiscounts(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_special_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 7.5, 'max_price' => 15, 'tier_price' => null], + ['simple1000' => 7.5, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product with special price + options with special prices + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php + * + * @return void + */ + public function testDynamicBundleProductWithSpecialPriceAndOptionsWithSpecialPrices(): void + { + $this->updateProducts($this->specialPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_special_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 6, 'max_price' => 11.25, 'tier_price' => null], + ['simple1000' => 6, 'simple1001' => 11.25] + ); + } + + /** + * Dynamic Bundle Product with special price + options with tier prices + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php + * + * @return void + */ + public function testDynamicBundleProductWithSpecialPriceAndOptionsWithTierPrices(): void + { + $this->updateProducts($this->tierPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_special_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 6, 'max_price' => 12.75, 'tier_price' => null], + ['simple1000' => 6, 'simple1001' => 12.75] + ); + } + + /** + * Dynamic Bundle Product with special price + options with catalog price rule + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php + * @magentoDataFixture Magento/CatalogRule/_files/catalog_rule_for_category_999.php + * + * @return void + */ + public function testDynamicBundleProductWithSpecialPriceAndOptionsWithCatalogPriceRule(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_special_price', + ['price' => 0, 'final_price' => 0, 'min_price' => 5.625, 'max_price' => 11.25, 'tier_price' => null], + ['simple1000' => 5.63, 'simple1001' => 11.25] + ); + } + + /** + * Dynamic Bundle Product with catalog price rule + options without discounts + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php + * + * @return void + */ + public function testDynamicBundleProductWithCatalogPriceRuleAndOptionsWithoutDiscounts(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_catalog_rule', + ['price' => 0, 'final_price' => 0, 'min_price' => 10, 'max_price' => 20, 'tier_price' => null], + ['simple1000' => 10, 'simple1001' => 20] + ); + } + + /** + * Dynamic Bundle Product with catalog price rule + options with catalog price rule + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php + * @magentoDataFixture Magento/CatalogRule/_files/catalog_rule_for_category_999.php + * + * @return void + */ + public function testDynamicBundleProductWithCatalogPriceRuleAndOptionsWithCatalogPriceRule(): void + { + $this->checkBundlePrices( + 'dynamic_bundle_product_with_catalog_rule', + ['price' => 0, 'final_price' => 0, 'min_price' => 7.5, 'max_price' => 15, 'tier_price' => null], + ['simple1000' => 7.5, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product with catalog price rule + options with special prices + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php + * + * @return void + */ + public function testDynamicBundleProductWithCatalogPriceRuleAndOptionsWithSpecialPrices(): void + { + $this->updateProducts($this->specialPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_catalog_rule', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 15, 'tier_price' => null], + ['simple1000' => 8, 'simple1001' => 15] + ); + } + + /** + * Dynamic Bundle Product with catalog price rule + options with tier price + * @magentoDataFixture Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php + * + * @return void + */ + public function testDynamicBundleProductWithCatalogPriceRuleAndOptionsWithTierPrice(): void + { + $this->updateProducts($this->tierPricesForOptionsData()); + $this->checkBundlePrices( + 'dynamic_bundle_product_with_catalog_rule', + ['price' => 0, 'final_price' => 0, 'min_price' => 8, 'max_price' => 17, 'tier_price' => null], + ['simple1000' => 8, 'simple1001' => 17] + ); + } + + /** + * Check bundle prices from index table and final bundle option price. + * + * @param string $sku + * @param array $indexPrices + * @param array $expectedPrices + * @return void + */ + private function checkBundlePrices(string $sku, array $indexPrices, array $expectedPrices): void + { + $product = $this->productRepository->get($sku); + $this->assertIndexTableData((int)$product->getId(), $indexPrices); + $this->assertPriceWithChosenOption($product, $expectedPrices); + } + + /** + * Asserts price data in index table. + * + * @param int $productId + * @param array $expectedPrices + * @return void + */ + private function assertIndexTableData(int $productId, array $expectedPrices): void + { + $data = $this->getPriceIndexDataByProductId->execute( + $productId, + Group::NOT_LOGGED_IN_ID, + (int)$this->websiteRepository->get('base')->getId() + ); + $data = reset($data); + foreach ($expectedPrices as $column => $price) { + $this->assertEquals($price, $data[$column]); + } + } + + /** + * Assert bundle final price with chosen option. + * + * @param ProductInterface $bundle + * @param array $expectedPrices + * @return void + */ + private function assertPriceWithChosenOption(ProductInterface $bundle, array $expectedPrices): void + { + $option = $bundle->getExtensionAttributes()->getBundleProductOptions()[0] ?? null; + $this->assertNotNull($option); + foreach ($option->getProductLinks() as $productLink) { + $bundle->addCustomOption('bundle_selection_ids', $this->json->serialize([$productLink->getId()])); + $bundle->addCustomOption('selection_qty_' . $productLink->getId(), 1); + $this->assertEquals( + round($expectedPrices[$productLink->getSku()], 2), + round($this->priceModel->getFinalPrice(1, $bundle), 2) + ); + } + } + + /** + * Update products. + * + * @param array $products + * @return void + */ + private function updateProducts(array $products): void + { + foreach ($products as $sku => $updateData) { + $product = $this->productRepository->get($sku); + $product->addData($updateData); + $this->productRepository->save($product); + } + } + + /** + * @return array + */ + private function specialPricesForOptionsData(): array + { + return [ + 'simple1000' => [ + 'special_price' => 8, + ], + 'simple1001' => [ + 'special_price' => 15, + ], + ]; + } + + /** + * @return array + */ + private function tierPricesForOptionsData(): array + { + return [ + 'simple1000' => [ + 'tier_price' => [ + [ + 'website_id' => 0, + 'cust_group' => Group::CUST_GROUP_ALL, + 'price_qty' => 1, + 'value_type' => TierPriceInterface::PRICE_TYPE_FIXED, + 'price' => 8, + ], + ], + ], + 'simple1001' => [ + 'tier_price' => [ + [ + 'website_id' => 0, + 'cust_group' => Group::CUST_GROUP_ALL, + 'price_qty' => 1, + 'value_type' => TierPriceInterface::PRICE_TYPE_DISCOUNT, + 'website_price' => 20, + 'percentage_value' => 15, + ], + ], + ], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php new file mode 100644 index 0000000000000..4b581a5cbf5d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Checkbox Options') + ->setSku('bundle-product-checkbox-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); + +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php new file mode 100644 index 0000000000000..3475737790c86 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php new file mode 100644 index 0000000000000..1cc9ede5d71e4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Checkbox Required Option') + ->setSku('bundle-product-checkbox-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php new file mode 100644 index 0000000000000..f75241fb8b680 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php new file mode 100644 index 0000000000000..5bb6fe6973287 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Checkbox Required Options') + ->setSku('bundle-product-checkbox-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Checkbox Options', + 'default_title' => 'Checkbox Options', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php new file mode 100644 index 0000000000000..f601d1d6793e6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-checkbox-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php new file mode 100644 index 0000000000000..62c80abc6415f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Dropdown options') + ->setSku('bundle-product-dropdown-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Dropdown Options', + 'default_title' => 'Dropdown Options', + 'type' => 'select', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php new file mode 100644 index 0000000000000..857e44d0298cb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-dropdown-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php new file mode 100644 index 0000000000000..4093c9ff057e7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Dropdown Required options') + ->setSku('bundle-product-dropdown-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Dropdown Options', + 'default_title' => 'Dropdown Options', + 'type' => 'select', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php new file mode 100644 index 0000000000000..ad4464153dbf1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-dropdown-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php new file mode 100644 index 0000000000000..29b7710c47040 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Multiselect Options') + ->setSku('bundle-product-multiselect-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php new file mode 100644 index 0000000000000..c02f218131b20 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php new file mode 100644 index 0000000000000..0cde1e65c9e54 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Multiselect Required Option') + ->setSku('bundle-product-multiselect-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php new file mode 100644 index 0000000000000..8e16ecb5f3890 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php new file mode 100644 index 0000000000000..f18494d08215c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Multiselect Required Options') + ->setSku('bundle-product-multiselect-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Multiselect Options', + 'default_title' => 'Multiselect Options', + 'type' => 'multi', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php new file mode 100644 index 0000000000000..bf78eece56938 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-multiselect-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php new file mode 100644 index 0000000000000..23a5713e46eb0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Radio Options') + ->setSku('bundle-product-radio-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 0, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php new file mode 100644 index 0000000000000..5630b2f88ba4d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php new file mode 100644 index 0000000000000..1472986023e21 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Radio Required Option') + ->setSku('bundle-product-radio-required-option') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php new file mode 100644 index 0000000000000..9a44ccbca6110 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-required-option', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php new file mode 100644 index 0000000000000..cb703902a0b7a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = $websiteRepository->get('base')->getId(); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsiteId]) + ->setName('Bundle Product Radio Required Options') + ->setSku('bundle-product-radio-required-options') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->setPriceView(0) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(10.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Radio Options', + 'default_title' => 'Radio Options', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + 'delete' => '', + 'option_id' => 1, + ], +]; + +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php new file mode 100644 index 0000000000000..8536a76979430 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_duplicated_rollback.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/second_product_simple_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); + +try { + $product = $productRepository->get('bundle-product-radio-required-options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php new file mode 100644 index 0000000000000..9a6cae37fbe25 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\CategoryLinkManagementInterface; +use Magento\Catalog\Helper\DefaultCategory; + +require __DIR__ . '/product.php'; +require __DIR__ . '/bundle_product_dropdown_options.php'; +require __DIR__ . '/../../Catalog/_files/category.php'; + +/** @var CategoryLinkManagementInterface $categoryLinkManagement */ +$categoryLinkManagement = $objectManager->create(CategoryLinkManagementInterface::class); +/** @var DefaultCategory $categoryHelper */ +$categoryHelper = $objectManager->get(DefaultCategory::class); +$categoryLinkManagement->assignProductToCategories('bundle-product', [2, $category->getId()]); +$categoryLinkManagement->assignProductToCategories( + 'bundle-product-dropdown-options', + [$categoryHelper->getId(), $category->getId()] +); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category_rollback.php new file mode 100644 index 0000000000000..58eb8cacde815 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category_rollback.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/product_rollback.php'; +require __DIR__ . '/bundle_product_dropdown_options_rollback.php'; +require __DIR__ . '/../../Catalog/_files/category_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php new file mode 100644 index 0000000000000..c9e2bfb74090b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Api\Data\LinkInterfaceFactory; +use Magento\Bundle\Api\Data\OptionInterfaceFactory; +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; + +require __DIR__ . '/multiple_products.php'; + +/** @var ProductExtensionFactory $extensionAttributesFactory */ +$extensionAttributesFactory = $objectManager->get(ProductExtensionFactory::class); +/** @var OptionInterfaceFactory $optionFactory */ +$optionFactory = $objectManager->get(OptionInterfaceFactory::class); +/** @var LinkInterfaceFactory $linkFactory */ +$linkFactory = $objectManager->get(LinkInterfaceFactory::class); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle_product') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setWeightType(0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER) + ->setBundleOptionsData( + [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'multi', + 'required' => 1, + ], + ] + )->setBundleSelectionsData( + [ + [ + [ + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'product_id' => $product2->getId(), + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'product_id' => $product3->getId(), + 'sku' => $product3->getSku(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + ], + ] + ] + ); + +$options = []; +foreach ($bundleProduct->getBundleOptionsData() as $key => $optionData) { + $option = $optionFactory->create(['data' => $optionData]); + $option->setSku($bundleProduct->getSku()); + $option->setOptionId(null); + $links = []; + foreach ($bundleProduct->getBundleSelectionsData()[$key] as $linkData) { + $link = $linkFactory->create(['data' => $linkData]); + $links[] = $link; + } + $option->setProductLinks($links); + $options[] = $option; +} +$extensionAttributes = $bundleProduct->getExtensionAttributes() ?: $extensionAttributesFactory->create(); +$extensionAttributes->setBundleProductOptions($options); +$bundleProduct->setExtensionAttributes($extensionAttributes); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php new file mode 100644 index 0000000000000..25ebbd14bfa39 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/multiple_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('bundle_product', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php new file mode 100644 index 0000000000000..44d995a4b8baf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Api\Data\RuleInterface; +use Magento\CatalogRule\Api\Data\RuleInterfaceFactory; +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\Rule\Condition\Combine; +use Magento\CatalogRule\Model\Rule\Condition\Product; +use Magento\Customer\Model\Group; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var RuleInterfaceFactory $catalogRuleFactory */ +$catalogRuleFactory = $objectManager->get(RuleInterfaceFactory::class); +/** @var CatalogRuleRepositoryInterface $catalogRuleRepository */ +$catalogRuleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); + +$category = $categoryFactory->create(); +$category->isObjectNew(true); +$category->setName('Category with bundle product and rule') + ->setParentId($categoryHelper->getId()) + ->setIsActive(true) + ->setPosition(1); +$category = $categoryRepository->save($category); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('dynamic_bundle_product_with_catalog_rule') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(null) + ->setWeightType(0) + ->setCategoryIds([$category->getId()]) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'select', + 'required' => 1, + ], +]; +$bundleSelectionsData = [ + [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + ] +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, $bundleSelectionsData); +$productRepository->save($bundleProduct); + +$ruleData = [ + RuleInterface::NAME => 'Rule for bundle product', + RuleInterface::IS_ACTIVE => 1, + 'website_ids' => [$defaultWebsiteId], + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + RuleInterface::DISCOUNT_AMOUNT => 50, + RuleInterface::SIMPLE_ACTION => 'by_percent', + 'conditions' => [ + '1' => [ + 'type' => Combine::class, + 'aggregator' => 'all', + 'value' => '1', + ], + '1--1' => [ + 'type' => Product::class, + 'attribute' => 'category_ids', + 'operator' => '==', + 'value' => $category->getId(), + ], + ], +]; +$catalogRule = $catalogRuleFactory->create(); +$catalogRule->loadPost($ruleData); +$catalogRuleRepository->save($catalogRule); +$indexBuilder->reindexFull(); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule_rollback.php new file mode 100644 index 0000000000000..cf3fd4a9e14ff --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule_rollback.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Catalog\Model\GetCategoryByName; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products_rollback.php'; + +/** @var GetCategoryByName $getCategoryByName */ +$getCategoryByName = $objectManager->create(GetCategoryByName::class); +/** @var CollectionFactory $ruleCollectionFactory */ +$ruleCollectionFactory = $objectManager->get(CollectionFactory::class); +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('dynamic_bundle_product_with_catalog_rule', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //product already deleted. +} + +$category = $getCategoryByName->execute('Category with bundle product and rule'); + +try { + $categoryRepository->delete($category); +} catch (NoSuchEntityException $e) { + //category already deleted. +} + +$ruleCollection = $ruleCollectionFactory->create(); +$ruleCollection->addFieldToFilter('name', 'Rule for bundle product'); +$ruleCollection->setPageSize(1); +$catalogRule = $ruleCollection->getFirstItem(); + +try { + $ruleRepository->delete($catalogRule); +} catch (Exception $ex) { + //Nothing to remove +} + +$indexBuilder->reindexFull(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php new file mode 100644 index 0000000000000..e5fef4e581595 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('dynamic_bundle_product_with_special_price') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(null) + ->setSpecialPrice(75) + ->setWeightType(0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'select', + 'required' => 1, + ], +]; +$bundleSelectionsData = [ + [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + ] +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, $bundleSelectionsData); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price_rollback.php new file mode 100644 index 0000000000000..0ec7cc98131d4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('dynamic_bundle_product_with_special_price', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //product already deleted. +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php new file mode 100644 index 0000000000000..b1cdfddd061bb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\Customer\Model\Group; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */ +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +/** @var $tierPriceExtensionAttributesFactory */ +$tierPriceExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('dynamic_bundle_product_with_tier_price') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(null) + ->setWeightType(0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'select', + 'required' => 1, + ], +]; +$bundleSelectionsData = [ + [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + ] +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, $bundleSelectionsData); + +$tierPriceExtensionAttribute = $tierPriceExtensionAttributesFactory->create( + [ + 'data' => [ + 'website_id' => 0, + 'percentage_value' => 25, + ] + ] +); +$tierPrices[] = $tierPriceFactory->create( + [ + 'data' => [ + 'customer_group_id' => Group::CUST_GROUP_ALL, + 'qty' => 1, + ] + ] +)->setExtensionAttributes($tierPriceExtensionAttribute); +$bundleProduct->setTierPrices($tierPrices); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price_rollback.php new file mode 100644 index 0000000000000..247e2400986d7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('dynamic_bundle_product_with_tier_price', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //product already deleted. +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php new file mode 100644 index 0000000000000..4b0b81f5d9f04 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('dynamic_bundle_product_without_discounts') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setSkuType(0) + ->setPriceView(0) + ->setPriceType(Price::PRICE_TYPE_DYNAMIC) + ->setPrice(null) + ->setWeightType(0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'select', + 'required' => 1, + ], +]; +$bundleSelectionsData = [ + [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 0, + 'selection_can_change_qty' => 1, + ], + ] +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, $bundleSelectionsData); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts_rollback.php new file mode 100644 index 0000000000000..cb785aee1ccd7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/../../../Magento/Catalog/_files/category_with_different_price_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('dynamic_bundle_product_without_discounts', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //product already deleted. +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price.php new file mode 100644 index 0000000000000..d7caba1dec4aa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/multiple_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('fixed_bundle_product_with_special_price') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setPriceView(1) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_FIXED) + ->setPrice(50.0) + ->setSpecialPrice(80) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 10, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product3->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price_rollback.php new file mode 100644 index 0000000000000..2fd27a34a1f2a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/multiple_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('fixed_bundle_product_with_special_price', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price.php new file mode 100644 index 0000000000000..64de77d87085d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Customer\Model\Group; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/multiple_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */ +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +/** @var $tierPriceExtensionAttributesFactory */ +$tierPriceExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('fixed_bundle_product_with_tier_price') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setPriceView(1) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_FIXED) + ->setPrice(50.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 10, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product3->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); + +$tierPriceExtensionAttribute = $tierPriceExtensionAttributesFactory->create( + [ + 'data' => [ + 'website_id' => 0, + 'percentage_value' => 25, + ] + ] +); +$tierPrices[] = $tierPriceFactory->create( + [ + 'data' => [ + 'customer_group_id' => Group::CUST_GROUP_ALL, + 'qty' => 1, + ] + ] +)->setExtensionAttributes($tierPriceExtensionAttribute); +$bundleProduct->setTierPrices($tierPrices); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price_rollback.php new file mode 100644 index 0000000000000..0e3be5936876a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/multiple_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('fixed_bundle_product_with_tier_price', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts.php new file mode 100644 index 0000000000000..1b5d6b2eb60d2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Bundle\Model\Product\Price; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; + +require __DIR__ . '/multiple_products.php'; + +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('fixed_bundle_product_without_discounts') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ) + ->setPriceView(1) + ->setSkuType(1) + ->setWeightType(1) + ->setPriceType(Price::PRICE_TYPE_FIXED) + ->setPrice(50.0) + ->setShipmentType(AbstractType::SHIPMENT_TOGETHER); + +$bundleOptionsData = [ + [ + 'title' => 'Option 1', + 'default_title' => 'Option 1', + 'type' => 'radio', + 'required' => 1, + 'delete' => '', + ], +]; +$bundleSelectionsData = [ + [ + 'sku' => $product->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 10, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product2->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 1, + 'selection_can_change_qty' => 1, + ], + [ + 'sku' => $product3->getSku(), + 'selection_qty' => 1, + 'selection_price_value' => 25, + 'selection_price_type' => 0, + 'selection_can_change_qty' => 1, + ], +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, [$bundleSelectionsData]); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts_rollback.php new file mode 100644 index 0000000000000..d6a301c7937d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; + +require __DIR__ . '/multiple_products_rollback.php'; + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $product = $productRepository->get('fixed_bundle_product_without_discounts', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php index 662b69c89bc6d..fa957a0bfd3f8 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/multiple_products.php @@ -3,31 +3,44 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Msrp\Model\Product\Attribute\Source\Type; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; -/** @var $product \Magento\Catalog\Model\Product */ -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$defaultWebsiteId = $websiteRepository->get('base')->getId(); +$product = $productFactory->create(); +$product->setTypeId(ProductType::TYPE_SIMPLE) ->setId(10) - ->setAttributeSetId(4) + ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setName('Simple Product') ->setSku('simple1') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(10) ->setWeight(1) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -36,29 +49,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); - $productRepository->save($product); -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product2 = $productFactory->create(); +$product2->setTypeId(ProductType::TYPE_SIMPLE) ->setId(11) - ->setAttributeSetId(4) + ->setAttributeSetId($product2->getDefaultAttributeSetId()) ->setName('Simple Product2') ->setSku('simple2') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_ON_GESTURE) + ->setMsrpDisplayActualPriceType(Type::TYPE_ON_GESTURE) ->setPrice(20) ->setWeight(1) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -67,24 +78,22 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product2); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product3 = $productFactory->create(); +$product3->setTypeId(ProductType::TYPE_SIMPLE) ->setId(12) - ->setAttributeSetId(4) + ->setAttributeSetId($product3->getDefaultAttributeSetId()) ->setName('Simple Product 3') ->setSku('simple3') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setPrice(30) ->setWeight(1) - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_IN_CATALOG) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -93,29 +102,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product3); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product4 = $productFactory->create(); +$product4->setTypeId(ProductType::TYPE_SIMPLE) ->setId(13) - ->setAttributeSetId(4) + ->setAttributeSetId($product4->getDefaultAttributeSetId()) ->setName('Simple Product 4') ->setSku('simple4') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(13) ->setWeight(12) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -124,29 +131,27 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); +$productRepository->save($product4); -$productRepository->save($product); - -$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class); -$product->isObjectNew(true); -$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) +$product5 = $productFactory->create(); +$product5->setTypeId(ProductType::TYPE_SIMPLE) ->setId(14) - ->setAttributeSetId(4) + ->setAttributeSetId($product5->getDefaultAttributeSetId()) ->setName('Simple Product 5') ->setSku('simple5') - ->setTaxClassId('none') + ->setTaxClassId(0) ->setDescription('description') ->setShortDescription('short description') ->setOptionsContainer('container1') - ->setMsrpDisplayActualPriceType(\Magento\Msrp\Model\Product\Attribute\Source\Type::TYPE_IN_CART) + ->setMsrpDisplayActualPriceType(Type::TYPE_IN_CART) ->setPrice(14) ->setWeight(10) ->setMetaTitle('meta title') ->setMetaKeyword('meta keyword') ->setMetaDescription('meta description') - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setWebsiteIds([1]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setWebsiteIds([$defaultWebsiteId]) ->setCategoryIds([]) ->setStockData([ 'use_config_manage_stock' => 1, @@ -155,5 +160,4 @@ 'is_in_stock' => 1, 'manage_stock' => 1, ]); - -$productRepository->save($product); +$productRepository->save($product5); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/CrosssellTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/CrosssellTest.php index bf546ccd979b7..e3d8e3b229ffa 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/CrosssellTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/CrosssellTest.php @@ -29,6 +29,7 @@ public function testAll() $block = $objectManager->get(\Magento\Framework\View\LayoutInterface::class) ->createBlock(\Magento\Catalog\Block\Product\ProductList\Crosssell::class); $block->setLayout($objectManager->get(\Magento\Framework\View\LayoutInterface::class)); + $block->setViewModel($objectManager->get(\Magento\Catalog\ViewModel\Product\Listing\PreparePostData::class)); $block->setTemplate('Magento_Catalog::product/list/items.phtml'); $block->setType('crosssell'); $block->setItemCount(1); @@ -36,7 +37,7 @@ public function testAll() $this->assertNotEmpty($html); $this->assertContains('Simple Cross Sell', $html); /* name */ - $this->assertContains('product\/' . $firstProduct->getId() . '\/', $html); + $this->assertContains('product/' . $firstProduct->getId() . '/', $html); /* part of url */ $this->assertInstanceOf( \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection::class, diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php index f979bad9d0f76..a4631526bd4c5 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php @@ -19,9 +19,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class CreateCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -46,8 +52,6 @@ protected function setUp() /** * Test add to product custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider productWithNewOptionsDataProvider * * @param array $productPostData @@ -57,7 +61,7 @@ protected function setUp() public function testSaveCustomOptionWithTypeField(array $productPostData): void { $this->getRequest()->setPostValue($productPostData); - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->dispatch('backend/catalog/product/save/id/' . $product->getEntityId()); $this->assertSessionMessages( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php index f1af6e6e41cff..6a4ff066f710d 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php @@ -21,9 +21,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class DeleteCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -54,8 +60,6 @@ protected function setUp() /** * Test delete custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Option\DataProvider\Type\Field::getDataForCreateOptions * * @param array $optionData @@ -63,7 +67,7 @@ protected function setUp() */ public function testDeleteCustomOptionWithTypeField(array $optionData): void { - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); /** @var ProductCustomOptionInterface $option */ $option = $this->optionRepositoryFactory->create(['data' => $optionData]); $option->setProductSku($product->getSku()); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php index a45c21444a5d7..1badf6a1a081a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php @@ -22,9 +22,15 @@ * * @magentoAppArea adminhtml * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Catalog/_files/product_without_options.php */ class UpdateCustomOptionsTest extends AbstractBackendController { + /** + * @var string + */ + protected $productSku = 'simple'; + /** * @var ProductRepositoryInterface */ @@ -55,8 +61,6 @@ protected function setUp() /** * Test add to product custom option with type "field". * - * @magentoDataFixture Magento/Catalog/_files/product_without_options.php - * * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Option\DataProvider\Type\Field::getDataForUpdateOptions * * @param array $optionData @@ -65,7 +69,7 @@ protected function setUp() */ public function testUpdateCustomOptionWithTypeField(array $optionData, array $updateData): void { - $product = $this->productRepository->get('simple'); + $product = $this->productRepository->get($this->productSku); /** @var ProductCustomOptionInterface|Option $option */ $option = $this->optionRepositoryFactory->create(['data' => $optionData]); $option->setProductSku($product->getSku()); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php index e1e4a87c033d0..c4cabe46f5b32 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/CategoryRepositoryTest.php @@ -9,10 +9,10 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\CategoryRepositoryInterfaceFactory; -use Magento\Framework\Exception\LocalizedException; -use Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; +use Magento\Framework\Exception\LocalizedException; +use Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -21,6 +21,11 @@ */ class CategoryRepositoryTest extends TestCase { + private const FIXTURE_CATEGORY_ID = 333; + private const FIXTURE_TWO_STORES_CATEGORY_ID = 555; + private const FIXTURE_SECOND_STORE_CODE = 'fixturestore'; + private const FIXTURE_FIRST_STORE_CODE = 'default'; + /** * @var CategoryLayoutUpdateManager */ @@ -77,13 +82,13 @@ public function testCustomLayout(): void { //New valid value $repo = $this->createRepo(); - $category = $repo->get(333); + $category = $repo->get(self::FIXTURE_CATEGORY_ID); $newFile = 'test'; - $this->layoutManager->setCategoryFakeFiles(333, [$newFile]); + $this->layoutManager->setCategoryFakeFiles(self::FIXTURE_CATEGORY_ID, [$newFile]); $category->setCustomAttribute('custom_layout_update_file', $newFile); $repo->save($category); $repo = $this->createRepo(); - $category = $repo->get(333); + $category = $repo->get(self::FIXTURE_CATEGORY_ID); $this->assertEquals($newFile, $category->getCustomAttribute('custom_layout_update_file')->getValue()); //Setting non-existent value @@ -126,4 +131,36 @@ public function testCategoryBehaviourAfterDelete(): void 'Wrong categories was deleted' ); } + + /** + * Verifies whether `get()` method `$storeId` attribute works as expected. + * + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/category_with_two_stores.php + */ + public function testGetCategoryForProvidedStore() + { + $categoryRepository = $this->repositoryFactory->create(); + + $categoryDefault = $categoryRepository->get( + self::FIXTURE_TWO_STORES_CATEGORY_ID + ); + + $this->assertSame('category-defaultstore', $categoryDefault->getUrlKey()); + + $categoryFirstStore = $categoryRepository->get( + self::FIXTURE_TWO_STORES_CATEGORY_ID, + self::FIXTURE_FIRST_STORE_CODE + ); + + $this->assertSame('category-defaultstore', $categoryFirstStore->getUrlKey()); + + $categorySecondStore = $categoryRepository->get( + self::FIXTURE_TWO_STORES_CATEGORY_ID, + self::FIXTURE_SECOND_STORE_CODE + ); + + $this->assertSame('category-fixturestore', $categorySecondStore->getUrlKey()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php index f3989248a8ed1..602af4d0e3c78 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/_files/attribute_with_option_rollback.php @@ -32,7 +32,7 @@ \Magento\Catalog\Model\Product::class ); $product = $product->loadByAttribute('sku', 'simple_product_' . $option->getId()); - if ($product->getId()) { + if ($product instanceof \Magento\Catalog\Model\Product && $product->getId()) { $product->delete(); } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ProductFrontendAction/SynchronizerTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ProductFrontendAction/SynchronizerTest.php index 3ea30005e9f6c..5cf53349480f1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ProductFrontendAction/SynchronizerTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ProductFrontendAction/SynchronizerTest.php @@ -40,20 +40,24 @@ protected function setUp() * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php * * @return void + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function testSyncActions(): void { $actionsType = 'recently_viewed_product'; + $productScope = 'website'; + $scopeId = 1; $product1 = $this->productRepository->get('simple'); $product2 = $this->productRepository->get('simple2'); $product1Id = $product1->getId(); $product2Id = $product2->getId(); $productsData = [ - $product1Id => [ + $productScope . '-' . $scopeId . '-' . $product1Id => [ 'added_at' => '1576582660', 'product_id' => $product1Id, ], - $product2Id => [ + $productScope . '-' . $scopeId . '-' . $product2Id => [ 'added_at' => '1576587153', 'product_id' => $product2Id, ], @@ -71,8 +75,9 @@ public function testSyncActions(): void ); foreach ($synchronizedCollection as $item) { - $this->assertArrayHasKey($item->getProductId(), $productsData); - $this->assertEquals($productsData[$item->getProductId()]['added_at'], $item->getAddedAt()); + $productScopeId = $productScope . '-' . $scopeId . '-' . $item->getProductId(); + $this->assertArrayHasKey($productScopeId, $productsData); + $this->assertEquals($productsData[$productScopeId]['added_at'], $item->getAddedAt()); } } @@ -81,6 +86,8 @@ public function testSyncActions(): void * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php * * @return void + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function testSyncActionsWithoutActionsType(): void { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php index ff2979150954e..451e19be28e5f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php @@ -53,8 +53,8 @@ public function testGetUrlInStore() * @magentoConfigFixture fixturestore_store web/unsecure/base_url http://sample-second.com/ * @magentoConfigFixture fixturestore_store web/unsecure/base_link_url http://sample-second.com/ * @magentoDataFixture Magento/Catalog/_files/product_simple_multistore.php - * @magentoDbIsolation disabled * @dataProvider getUrlsWithSecondStoreProvider + * @magentoDbIsolation disabled * @magentoAppArea adminhtml */ public function testGetUrlInStoreWithSecondStore($storeCode, $expectedProductUrl) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php index 6baaf4940f94f..5b55bb32ce669 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php @@ -171,7 +171,7 @@ public function tierPricesForAllCustomerGroupsDataProvider(): array [ ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 2, 'percent_value' => 70], ], - ['qty' => 2, 'price' => 3.00, 'percent' => 70], + ['qty' => 2, 'price' => 3.00, 'percent' => 50], ], 'fixed_tier_price_with_qty_1_is_lower_than_special' => [ 5, @@ -313,7 +313,7 @@ public function catalogRulesDataProvider(): array [ ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 2, 'percent_value' => 70], ], - ['qty' => 2, 'price' => 3.00, 'percent' => 70], + ['qty' => 2, 'price' => 3.00, 'percent' => 25], ], 'fixed_catalog_rule_price_lower_than_tier_price' => [ 2, diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_different_price_products.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_different_price_products.php index 2e87e1e820f86..daa7f9f61a841 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_different_price_products.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/category_with_different_price_products.php @@ -15,20 +15,30 @@ use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\Catalog\Helper\DefaultCategory; $objectManager = Bootstrap::getObjectManager(); +/** @var StoreManagerInterface $storeManager */ $storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var CategoryInterfaceFactory $categoryFactory */ $categoryFactory = $objectManager->get(CategoryInterfaceFactory::class); +/** @var ProductInterfaceFactory $productFactory */ $productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var CategoryRepositoryInterface $categoryRepository */ $categoryRepository = $objectManager->get(CategoryRepositoryInterface::class); +/** @var DefaultCategory $categoryHelper */ +$categoryHelper = $objectManager->get(DefaultCategory::class); $currentStoreId = $storeManager->getStore()->getId(); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); $storeManager->setCurrentStore(Store::DEFAULT_STORE_ID); $category = $categoryFactory->create(); $category->isObjectNew(true); $category->setName('Category 999') - ->setParentId(2) + ->setParentId($categoryHelper->getId()) ->setLevel(2) ->setAvailableSortBy('name') ->setDefaultSortBy('name') @@ -41,7 +51,7 @@ $product->setTypeId(Type::TYPE_SIMPLE) ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setStoreId(Store::DEFAULT_STORE_ID) - ->setWebsiteIds([1]) + ->setWebsiteIds([$defaultWebsiteId]) ->setName('Simple Product With Price 10') ->setSku('simple1000') ->setPrice(10) @@ -52,11 +62,11 @@ ->setStatus(Status::STATUS_ENABLED); $productRepository->save($product); -$product = $productFactory->create(); -$product->setTypeId(Type::TYPE_SIMPLE) - ->setAttributeSetId($product->getDefaultAttributeSetId()) +$product2 = $productFactory->create(); +$product2->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId($product2->getDefaultAttributeSetId()) ->setStoreId(Store::DEFAULT_STORE_ID) - ->setWebsiteIds([1]) + ->setWebsiteIds([$defaultWebsiteId]) ->setName('Simple Product With Price 20') ->setSku('simple1001') ->setPrice(20) @@ -65,4 +75,4 @@ ->setCategoryIds([$category->getId()]) ->setVisibility(Visibility::VISIBILITY_BOTH) ->setStatus(Status::STATUS_ENABLED); -$productRepository->save($product); +$productRepository->save($product2); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute.php new file mode 100644 index 0000000000000..e2a5f560c8b7b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Eav\Model\Config; + +require __DIR__ . '/product_varchar_attribute.php'; +require __DIR__ . '/product_simple.php'; + +/** @var Config $eavConfig */ +$eavConfig = $objectManager->get(Config::class); +$eavConfig->clear(); + +$attribute->setDefaultValue('Varchar default value'); +$attributeRepository->save($attribute); + +$product->setCustomAttribute('varchar_attribute', $attribute->getDefaultValue()); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute_rollback.php new file mode 100644 index 0000000000000..5d6b5dce4b541 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute_rollback.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/product_varchar_attribute_rollback.php'; +require __DIR__ . '/product_simple_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index f24981ca40156..93684b1e7a070 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -5,11 +5,6 @@ */ declare(strict_types=1); -/** - * Test class for \Magento\CatalogImportExport\Model\Import\Product - * - * The "CouplingBetweenObjects" warning is caused by tremendous complexity of the original class - */ namespace Magento\CatalogImportExport\Model\Import; use Magento\Catalog\Api\Data\ProductInterface; @@ -18,10 +13,13 @@ use Magento\Catalog\Model\Category; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\CatalogImportExport\Model\Import\Product as ImportProduct; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; use Magento\CatalogInventory\Model\Stock; use Magento\CatalogInventory\Model\StockRegistry; use Magento\CatalogInventory\Model\StockRegistryStorage; +use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; @@ -29,7 +27,9 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Filesystem; use Magento\Framework\Registry; +use Magento\ImportExport\Helper\Data; use Magento\ImportExport\Model\Import; +use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; use Magento\ImportExport\Model\Import\Source\Csv; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; @@ -38,7 +38,8 @@ use Psr\Log\LoggerInterface; /** - * Class ProductTest + * Integration test for \Magento\CatalogImportExport\Model\Import\Product class. + * * @magentoAppIsolation enabled * @magentoDbIsolation enabled * @magentoAppArea adminhtml @@ -81,6 +82,19 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase */ private $logger; + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -92,6 +106,8 @@ protected function setUp() ['logger' => $this->logger] ); $this->importedProducts = []; + $this->searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); parent::setUp(); } @@ -2400,6 +2416,16 @@ public function validateRowDataProvider() 'behavior' => Import::BEHAVIOR_REPLACE, 'expectedResult' => true, ], + [ + 'row' => ['sku' => 'sku with whitespace ', + 'name' => 'Test', + 'product_type' => 'simple', + '_attribute_set' => 'Default', + 'price' => 10.20, + ], + 'behavior' => Import::BEHAVIOR_ADD_UPDATE, + 'expectedResult' => false, + ], ]; } @@ -2674,35 +2700,46 @@ public function testImportWithBackordersDisabled(): void } /** - * Import file by providing import filename in parameters. + * Import file by providing import filename and bunch size. * * @param string $fileName - * @return void + * @param int $bunchSize + * @return bool */ - private function importFile(string $fileName): void + private function importFile(string $fileName, int $bunchSize = 100): bool { - $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class); + $importExportData = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->getMock(); + $importExportData->expects($this->atLeastOnce()) + ->method('getBunchSize') + ->willReturn($bunchSize); + $this->_model = $this->objectManager->create( + ImportProduct::class, + ['importExportData' => $importExportData] + ); + $filesystem = $this->objectManager->create(Filesystem::class); $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); $source = $this->objectManager->create( - \Magento\ImportExport\Model\Import\Source\Csv::class, + Csv::class, [ - 'file' => __DIR__ . '/_files/' . $fileName, + 'file' => __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $fileName, 'directory' => $directory, ] ); $errors = $this->_model->setParameters( [ - 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'behavior' => Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product', - \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE => 1, + Import::FIELDS_ENCLOSURE => 1, ] ) - ->setSource($source) - ->validateData(); + ->setSource($source) + ->validateData(); - $this->assertTrue($errors->getErrorsCount() == 0); + $this->assertTrue($errors->getErrorsCount() === 0); - $this->_model->importData(); + return $this->_model->importData(); } /** @@ -3023,4 +3060,54 @@ public function testProductStockStatusShouldBeUpdatedOnSchedule() $status = $stockRegistry->getStockStatusBySku('simple'); $this->assertEquals(Stock::STOCK_IN_STOCK, $status->getStockStatus()); } + + /** + * Tests that empty attribute value in the CSV file will be ignored after update a product by the import. + * + * @magentoDataFixture Magento/Catalog/_files/product_with_varchar_attribute.php + */ + public function testEmptyAttributeValueShouldBeIgnoredAfterUpdateProductByImport() + { + $pathToFile = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR + . 'import_product_with_empty_attribute_value.csv'; + /** @var ImportProduct $importModel */ + $importModel = $this->createImportModel($pathToFile); + /** @var ProcessingErrorAggregatorInterface $errors */ + $errors = $importModel->validateData(); + $this->assertTrue($errors->getErrorsCount() === 0, 'Import file validation failed.'); + $importModel->importData(); + + $simpleProduct = $this->productRepository->get('simple', false, null, true); + $this->assertEquals('Varchar default value', $simpleProduct->getData('varchar_attribute')); + $this->assertEquals('Short description', $simpleProduct->getData('short_description')); + } + + /** + * Checks possibility to double importing products using the same import file. + * + * Bunch size is using to test importing the same product that will be chunk to different bunches. + * Example: + * - first bunch + * product-sku,default-store + * product-sku,second-store + * - second bunch + * product-sku,third-store + * + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php + * @magentoDataFixture Magento/Store/_files/second_store.php + */ + public function testCheckDoubleImportOfProducts() + { + /** @var SearchCriteria $searchCriteria */ + $searchCriteria = $this->searchCriteriaBuilder->create(); + + $this->assertEquals(true, $this->importFile('products_with_two_store_views.csv', 2)); + $productsAfterFirstImport = $this->productRepository->getList($searchCriteria)->getItems(); + $this->assertEquals(3, count($productsAfterFirstImport)); + + $this->assertEquals(true, $this->importFile('products_with_two_store_views.csv', 2)); + $productsAfterSecondImport = $this->productRepository->getList($searchCriteria)->getItems(); + $this->assertEquals(3, count($productsAfterSecondImport)); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_product_with_empty_attribute_value.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_product_with_empty_attribute_value.csv new file mode 100644 index 0000000000000..8ebaf0b64319e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_product_with_empty_attribute_value.csv @@ -0,0 +1,2 @@ +sku,name,short_description,product_type,attribute_set_code,price,qty,additional_attributes +simple,Simple Product,,simple,Default,10,100,varchar_attribute= diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_two_store_views.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_two_store_views.csv new file mode 100644 index 0000000000000..38667c7898160 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_two_store_views.csv @@ -0,0 +1,10 @@ +sku,name,store_view_code,product_type,attribute_set_code,price,custom_options +simple1,Simple 1,,simple,Default,100,"name=Test Option 1,type=field" +simple1,Simple 1,fixturestore,simple,Default,,"name=Test Option 1,type=field" +simple1,Simple 1,fixture_second_store,simple,Default,,"name=Test Option 1,type=field" +simple2,Simple 2,,simple,Default,200,"name=Test Option 1,type=field" +simple2,Simple 2,fixturestore,simple,Default,,"name=Test Option 1,type=field" +simple2,Simple 2,fixture_second_store,simple,Default,,"name=Test Option 1,type=field" +simple3,Simple 3,,simple,Default,300,"name=Test Option 1,type=field" +simple3,Simple 3,fixturestore,simple,Default,,"name=Test Option 1,type=field" +simple3,Simple 3,fixture_second_store,simple,Default,,"name=Test Option 1,type=field" diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999.php new file mode 100644 index 0000000000000..32815134c78a1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Api\Data\RuleInterface; +use Magento\CatalogRule\Api\Data\RuleInterfaceFactory; +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\Rule\Condition\Combine; +use Magento\CatalogRule\Model\Rule\Condition\Product; +use Magento\Customer\Model\Group; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Catalog\Model\GetCategoryByName; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$defaultWebsiteId = $websiteRepository->get('base')->getId(); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +/** @var CatalogRuleRepositoryInterface $catalogRuleRepository */ +$catalogRuleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var RuleInterfaceFactory $ruleFactory */ +$catalogRuleFactory = $objectManager->get(RuleInterfaceFactory::class); +/** @var GetCategoryByName $getCategoryByName */ +$getCategoryByName = $objectManager->get(GetCategoryByName::class); + +$category = $getCategoryByName->execute('Category 999'); +if ($category->getId()) { + $ruleData = [ + RuleInterface::NAME => 'Catalog rule for category 999', + RuleInterface::IS_ACTIVE => 1, + 'website_ids' => [$defaultWebsiteId], + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + RuleInterface::DISCOUNT_AMOUNT => 25, + RuleInterface::SIMPLE_ACTION => 'by_percent', + 'conditions' => [ + '1' => [ + 'type' => Combine::class, + 'aggregator' => 'all', + 'value' => '1', + ], + '1--1' => [ + 'type' => Product::class, + 'attribute' => 'category_ids', + 'operator' => '==', + 'value' => $category->getId(), + ], + ], + ]; + $catalogRule = $catalogRuleFactory->create(); + $catalogRule->loadPost($ruleData); + $catalogRuleRepository->save($catalogRule); + $indexBuilder->reindexFull(); +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999_rollback.php new file mode 100644 index 0000000000000..f7af2256575b8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999_rollback.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$catalogRuleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var CollectionFactory $ruleCollectionFactory */ +$ruleCollectionFactory = $objectManager->get(CollectionFactory::class); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); + +$ruleCollection = $ruleCollectionFactory->create(); +$ruleCollection->addFieldToFilter('name', 'Catalog rule for category 999'); +$ruleCollection->setPageSize(1); +$catalogRule = $ruleCollection->getFirstItem(); +if ($catalogRule->getId()) { + $catalogRuleRepository->delete($catalogRule); +} +$indexBuilder->reindexFull(); diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index 9c02623085cab..e36e3dee65954 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php @@ -5,20 +5,94 @@ */ namespace Magento\CatalogSearch\Block; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\Text; +use Magento\Framework\View\LayoutInterface; +use Magento\Search\Model\QueryFactory; +use Magento\TestFramework\Helper\Bootstrap; + class ResultTest extends \PHPUnit\Framework\TestCase { + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var LayoutInterface + */ + private $layout; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + } + public function testSetListOrders() { - /** @var $layout \Magento\Framework\View\Layout */ - $layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Framework\View\LayoutInterface::class - ); - $layout->addBlock(\Magento\Framework\View\Element\Text::class, 'head'); + $this->layout->addBlock(Text::class, 'head'); // The tested block is using head block - /** @var $block \Magento\CatalogSearch\Block\Result */ - $block = $layout->addBlock(\Magento\CatalogSearch\Block\Result::class, 'block'); - $childBlock = $layout->addBlock(\Magento\Framework\View\Element\Text::class, 'search_result_list', 'block'); + /** @var $block Result */ + $block = $this->layout->addBlock(Result::class, 'block'); + $childBlock = $this->layout->addBlock(Text::class, 'search_result_list', 'block'); $this->assertSame($childBlock, $block->getListBlock()); } + + /** + * Verify search value escaping process + * + * @magentoConfigFixture default/catalog/search/engine elasticsearch6 + * @dataProvider toEscapeSearchTextDataProvider + * @magentoAppArea frontend + * @param string $searchValue + * @param string $expectedOutput + * @param string $unexpectedOutput + * @return void + */ + public function testEscapeSearchText(string $searchValue, string $expectedOutput, string $unexpectedOutput): void + { + /** @var Result $searchResultBlock */ + $searchResultBlock = $this->layout->createBlock(Result::class); + /** @var Template $searchBlock */ + $searchBlock = $this->layout->createBlock(Template::class); + $searchBlock->setTemplate('Magento_Search::form.mini.phtml'); + /** @var RequestInterface $request */ + $request = $this->objectManager->get(RequestInterface::class); + + $request->setParam(QueryFactory::QUERY_VAR_NAME, $searchValue); + $searchHtml = $searchBlock->toHtml(); + + $this->assertContains('value=' . '"' . $expectedOutput . '"', $searchHtml); + $this->assertNotContains($unexpectedOutput, $searchHtml); + + $resultTitle = $searchResultBlock->getSearchQueryText()->render(); + $this->assertContains("Search results for: '{$expectedOutput}'", $resultTitle); + $this->assertNotContains($unexpectedOutput, $resultTitle); + } + + /** + * DataProvider for testEscapeSearchText() + * + * @return array + */ + public function toEscapeSearchTextDataProvider(): array + { + return [ + 'less_than_sign_escaped' => ['<', '<', '&lt;'], + 'greater_than_sign_escaped' => ['>', '>', '&gt;'], + 'ampersand_sign_escaped' => ['&', '&', '&amp;'], + 'double_quote_sign_escaped' => ['"', '"', '&quot;'], + 'single_quote_sign_escaped' => ["'", ''', '&#039;'], + 'plus_sign_not_escaped' => ['+', '+', '&+;'], + 'characters_not_escaped' => ['abc', 'abc', '&abc;'], + 'numbers_not_escaped' => ['123', '123', '&123;'], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogWidget/Block/Product/ProductListTest.php b/dev/tests/integration/testsuite/Magento/CatalogWidget/Block/Product/ProductListTest.php index f11083dd2ba91..8bcd0001b8119 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogWidget/Block/Product/ProductListTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogWidget/Block/Product/ProductListTest.php @@ -256,4 +256,80 @@ public function testCreateAnchorCollection() "Anchor root category does not contain products of it's children." ); } + + /** + * Test that price rule condition works correctly + * + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Catalog/_files/category_with_different_price_products.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @param string $operator + * @param int $value + * @param array $matches + * @dataProvider priceFilterDataProvider + */ + public function testPriceFilter(string $operator, int $value, array $matches) + { + $encodedConditions = '^[`1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Combine`, + `aggregator`:`all`,`value`:`1`,`new_child`:``^], + `1--1`:^[`type`:`Magento||CatalogWidget||Model||Rule||Condition||Product`, + `attribute`:`price`, + `operator`:`' . $operator . '`,`value`:`' . $value . '`^]^]'; + + $this->block->setData('conditions_encoded', $encodedConditions); + + $productCollection = $this->block->createCollection(); + $productCollection->load(); + $skus = array_map( + function ($item) { + return $item['sku']; + }, + $productCollection->getItems() + ); + $this->assertEquals($matches, $skus, '', 0.0, 10, true); + } + + public function priceFilterDataProvider(): array + { + return [ + [ + '>', + 10, + [ + 'simple1001', + ] + ], + [ + '>=', + 10, + [ + 'simple1000', + 'simple1001', + 'configurable', + ] + ], + [ + '<', + 10, + [] + ], + [ + '<', + 20, + [ + 'simple1000', + 'configurable', + ] + ], + [ + '<=', + 20, + [ + 'simple1000', + 'simple1001', + 'configurable', + ] + ], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Api/GuestShippingInformationManagementTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Api/GuestShippingInformationManagementTest.php index 50b1256c0f124..8018f76567d16 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/Api/GuestShippingInformationManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/Api/GuestShippingInformationManagementTest.php @@ -11,6 +11,7 @@ use Magento\Checkout\Api\Data\ShippingInformationInterfaceFactory; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\InputException; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\ShippingAssignmentInterface; use Magento\TestFramework\Helper\Bootstrap; @@ -53,6 +54,9 @@ class GuestShippingInformationManagementTest extends TestCase */ private $maskFactory; + /** + * @inheritdoc + */ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); @@ -73,10 +77,8 @@ protected function setUp() * @magentoDataFixture Magento/Sales/_files/quote.php * @magentoDataFixture Magento/Customer/_files/customer_with_addresses.php * @dataProvider getAddressesVariation - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The shipping information was unable to be saved. Verify the input data and try again. */ - public function testDifferentAddresses(bool $swapShipping) + public function testDifferentAddresses(bool $swapShipping): void { $carts = $this->cartRepo->getList( $this->searchCriteria->addFilter('reserved_order_id', 'test01')->create() @@ -107,6 +109,14 @@ public function testDifferentAddresses(bool $swapShipping) /** @var QuoteIdMask $idMask */ $idMask = $this->maskFactory->create(); $idMask->load($cart->getId(), 'quote_id'); + + $this->expectExceptionMessage( + sprintf( + 'The shipping information was unable to be saved. Error: "Invalid customer address id %s"', + $address->getCustomerAddressId() + ) + ); + $this->expectException(InputException::class); $this->management->saveAddressInformation($idMask->getMaskedId(), $shippingInformation); } diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Api/PaymentInformationManagementTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Api/PaymentInformationManagementTest.php deleted file mode 100644 index 1266dc7bb8843..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/Api/PaymentInformationManagementTest.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Checkout\Api; - -use Braintree\Result\Error; -use Magento\Braintree\Gateway\Http\Client\TransactionSale; -use Magento\Braintree\Model\Ui\ConfigProvider; -use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\App\State; -use Magento\Framework\App\Area; -use Magento\Quote\Api\CartRepositoryInterface; -use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Api\Data\PaymentInterface; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; -use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject as MockObject; - -/** - * Class PaymentInformationManagementTest - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class PaymentInformationManagementTest extends TestCase -{ - /** - * @var ObjectManager - */ - private $objectManager; - - /** - * @var TransactionSale|MockObject - */ - private $client; - - /** - * @inheritdoc - */ - protected function setUp() - { - $this->objectManager = Bootstrap::getObjectManager(); - - $this->client = $this->getMockBuilder(TransactionSale::class) - ->disableOriginalConstructor() - ->getMock(); - $this->objectManager->addSharedInstance($this->client, TransactionSale::class); - } - - /** - * @inheritdoc - */ - protected function tearDown() - { - $this->objectManager->removeSharedInstance(TransactionSale::class); - parent::tearDown(); - } - - /** - * Checks a case when payment method triggers an error during place order flow and - * error messages from payment gateway should be mapped. - * Error messages might be specific for different areas. - * - * @magentoAppIsolation enabled - * @magentoDataFixture Magento/Checkout/_files/quote_with_shipping_method.php - * @magentoConfigFixture current_store payment/braintree/active 1 - * @dataProvider getErrorPerAreaDataProvider - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @param string $area - * @param array $testErrorCodes - * @param string $expectedOutput - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testSavePaymentInformationAndPlaceOrderWithErrors( - string $area, - array $testErrorCodes, - string $expectedOutput - ) { - /** @var State $state */ - $state = $this->objectManager->get(State::class); - $state->setAreaCode($area); - - $quote = $this->getQuote('test_order_1'); - - /** @var PaymentInterface $payment */ - $payment = $this->objectManager->create(PaymentInterface::class); - $payment->setMethod(ConfigProvider::CODE); - - $errors = ['errors' => []]; - - foreach ($testErrorCodes as $testErrorCode) { - array_push($errors['errors'], ['code' => $testErrorCode]); - } - - $response = new Error(['errors' => $errors, 'transaction' => ['status' => 'declined']]); - - $this->client->method('placeRequest') - ->willReturn(['object' => $response]); - - $this->expectExceptionMessage($expectedOutput); - - /** @var PaymentInformationManagementInterface $paymentInformationManagement */ - $paymentInformationManagement = $this->objectManager->get(PaymentInformationManagementInterface::class); - $paymentInformationManagement->savePaymentInformationAndPlaceOrder( - $quote->getId(), - $payment - ); - } - - /** - * Gets list of areas with specific error messages. - * - * @return array - */ - public function getErrorPerAreaDataProvider() - { - $testErrorGlobal = ['code' => 81802, 'message' => 'Company is too long.']; - $testErrorAdmin = ['code' => 91511, 'message' => 'Customer does not have any credit cards.']; - $testErrorFake = ['code' => 'fake_code', 'message' => 'Error message should not be mapped.']; - - return [ - [ - Area::AREA_FRONTEND, - [$testErrorAdmin['code'], $testErrorFake['code']], - 'Transaction has been declined. Please try again later.' - ], [ - Area::AREA_FRONTEND, - [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']], - $testErrorGlobal['message'] - ], [ - Area::AREA_ADMINHTML, - [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']], - $testErrorGlobal['message'] . PHP_EOL . $testErrorAdmin['message'] - ], - ]; - } - - /** - * Retrieves quote by provided order ID. - * - * @param string $reservedOrderId - * @return CartInterface - */ - private function getQuote(string $reservedOrderId): CartInterface - { - /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ - $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); - $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId) - ->create(); - - /** @var CartRepositoryInterface $quoteRepository */ - $quoteRepository = $this->objectManager->get(CartRepositoryInterface::class); - $items = $quoteRepository->getList($searchCriteria) - ->getItems(); - - return array_pop($items); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Api/ShippingInformationManagementTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Api/ShippingInformationManagementTest.php index 7440fb7fd3d98..a0ccc5014bc19 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/Api/ShippingInformationManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/Api/ShippingInformationManagementTest.php @@ -13,6 +13,7 @@ use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\ShippingAssignmentInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Exception\InputException; use PHPUnit\Framework\TestCase; /** @@ -40,6 +41,9 @@ class ShippingInformationManagementTest extends TestCase */ private $shippingFactory; + /** + * @inheritdoc + */ protected function setUp() { $objectManager = Bootstrap::getObjectManager(); @@ -58,10 +62,8 @@ protected function setUp() * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php * @magentoDataFixture Magento/Customer/_files/customer_with_addresses.php * @dataProvider getAddressesVariation - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The shipping information was unable to be saved. Verify the input data and try again. */ - public function testDifferentAddresses(bool $swapShipping) + public function testDifferentAddresses(bool $swapShipping): void { $cart = $this->cartRepo->getForCustomer(1); $otherCustomer = $this->customerRepo->get('customer_with_addresses@test.com'); @@ -86,6 +88,14 @@ public function testDifferentAddresses(bool $swapShipping) $shippingInformation->setBillingAddress($billingAddress); $shippingInformation->setShippingAddress($shippingAddress); $shippingInformation->setShippingMethodCode('flatrate'); + + $this->expectExceptionMessage( + sprintf( + 'The shipping information was unable to be saved. Error: "Invalid customer address id %s"', + $address->getCustomerAddressId() + ) + ); + $this->expectException(InputException::class); $this->management->saveAddressInformation($cart->getId(), $shippingInformation); } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/RelatedTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/RelatedTest.php new file mode 100644 index 0000000000000..8543b2600138b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/RelatedTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Block\Product\ProductList; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Block\Product\ProductList\AbstractLinksTest; +use Magento\Catalog\Block\Product\ProductList\Related; + +/** + * Check the correct behavior of related products on the configurable product view page + + * @magentoDbIsolation disabled + * @magentoAppArea frontend + */ +class RelatedTest extends AbstractLinksTest +{ + /** + * @var Related + */ + protected $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->block = $this->layout->createBlock(Related::class); + $this->linkType = 'related'; + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @return void + */ + public function testRenderConfigurableWithLinkedProduct(): void + { + $this->linkProducts('configurable', ['simple2' => ['position' => 1]]); + $relatedProduct = $this->productRepository->get('simple2'); + $this->block->setProduct($this->productRepository->get('configurable')); + $this->prepareBlock(); + $html = $this->block->toHtml(); + $this->assertNotEmpty($html); + $this->assertContains($relatedProduct->getName(), $html); + $this->assertCount(1, $this->block->getItems()); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @return void + */ + public function testRenderConfigurableWithLinkedProductOnChild(): void + { + $this->linkProducts('simple_10', ['simple2' => ['position' => 1]]); + $relatedProduct = $this->productRepository->get('simple2'); + $this->block->setProduct($this->productRepository->get('configurable')); + $this->prepareBlock(); + $html = $this->block->toHtml(); + $this->assertNotEmpty($html); + $this->assertNotContains($relatedProduct->getName(), $html); + $this->assertEmpty($this->block->getItems()); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/products_list.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @return void + */ + public function testLinkedProductsPosition(): void + { + $this->linkProducts( + 'configurable', + ['wrong-simple' => ['position' => 3], 'simple-249' => ['position' => 2], 'simple-156' => ['position' => 1]] + ); + $this->block->setProduct($this->productRepository->get('configurable')); + $this->assertEquals( + ['simple-156', 'simple-249','wrong-simple'], + $this->getActualLinks($this->getLinkedItems()), + 'Expected linked products do not match actual linked products!' + ); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @return void + */ + public function testGetIdentities(): void + { + $this->linkProducts('configurable', ['simple2' => ['position = 1']]); + $relatedProduct = $this->productRepository->get('simple2'); + $this->block->setProduct($this->productRepository->get('configurable')); + $this->prepareBlock(); + $this->assertEquals(['cat_p_' . $relatedProduct->getId(), 'cat_p'], $this->block->getIdentities()); + } + + /** + * Returns linked products from block. + * + * @return ProductInterface[] + */ + protected function getLinkedItems(): array + { + return $this->block->getItems()->getItems(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/UpsellTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/UpsellTest.php new file mode 100644 index 0000000000000..ad24b84533c79 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/UpsellTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Block\Product\ProductList; + +use Magento\Catalog\Block\Product\ProductList\Upsell; + +/** + * Check the correct behavior of up-sell products on the configurable product view page + * + * @magentoDbIsolation disabled + * @magentoAppArea frontend + */ +class UpsellTest extends RelatedTest +{ + /** + * @var Upsell + */ + protected $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->block = $this->layout->createBlock(Upsell::class); + $this->linkType = 'upsell'; + } + + /** + * @inheritdoc + */ + protected function getLinkedItems(): array + { + return $this->block->getItems(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php new file mode 100644 index 0000000000000..20cfbda0ac920 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\CreateCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for configurable product custom options with type "field". + * Option add via dispatch product controller action save with options data in POST data. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class CreateCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php new file mode 100644 index 0000000000000..58b7f0e56fb0c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\DeleteCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for delete configurable product custom option with type "field". + * Option deleting via product controller action save. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class DeleteCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php new file mode 100644 index 0000000000000..ab0b03489cb92 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Controller\Adminhtml\Product\Save; + +use Magento\Catalog\Controller\Adminhtml\Product\Save\UpdateCustomOptionsTest as SimpleProductOptionsTest; + +/** + * Base test cases for update configurable product custom options with type "field". + * Option updating via dispatch product controller action save with updated options data in POST data. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ +class UpdateCustomOptionsTest extends SimpleProductOptionsTest +{ + /** + * @var string + */ + protected $productSku = 'configurable'; +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php new file mode 100644 index 0000000000000..cc087e006025d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Block\Account; + +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class checks password reset block output + * + * @see \Magento\Customer\Block\Account\Resetpassword + * @magentoAppArea frontend + */ +class ResetPasswordTest extends TestCase +{ + private const FORM_XPATH = "//form[contains(@action, '?token=%s')]"; + private const SET_NEW_PASSWORD_BUTTON_XPATH = "//button/span[contains(text(),'Set a New Password')]"; + private const NEW_PASSWORD_LABEL_XPATH = "//label[@for='password']/span[contains(text(), 'New Password')]"; + private const PASSWORD_CONFIRMATION_LABEL_XPATH = "//label[@for='password-confirmation']" + . "/span[contains(text(), 'Confirm New Password')]"; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var Resetpassword */ + private $block; + + /** @var Random */ + private $random; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->random = $this->objectManager->get(Random::class); + $this->block = $this->layout->createBlock(Resetpassword::class); + $this->block->setTemplate('Magento_Customer::form/resetforgottenpassword.phtml'); + } + + /** + * @return void + */ + public function testResetPasswordForm(): void + { + $token = $this->random->getUniqueHash(); + $this->block->setResetPasswordLinkToken($token); + $output = $this->block->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf(self::FORM_XPATH, $token), $output), + 'Form action does not include correct token' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::NEW_PASSWORD_LABEL_XPATH, $output), + 'New password label was not found on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::PASSWORD_CONFIRMATION_LABEL_XPATH, $output), + 'Confirm password label was not found on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::SET_NEW_PASSWORD_BUTTON_XPATH, $output), + 'Set password button was not found on the page' + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders/RenderOrdersTabTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders/RenderOrdersTabTest.php new file mode 100644 index 0000000000000..1d18814487bf8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders/RenderOrdersTabTest.php @@ -0,0 +1,433 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Block\Adminhtml\Edit\Tab\Orders; + +use Magento\Customer\Block\Adminhtml\Edit\Tab\Orders; +use Magento\Customer\Controller\RegistryConstants; +use Magento\Directory\Model\Currency; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Locale\CurrencyInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\Document; +use Magento\Framework\View\LayoutInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Store\Model\System\Store; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Test cases related to check that orders tab with customer orders + * grid correctly renders and contains all necessary data. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + */ +class RenderOrdersTabTest extends TestCase +{ + private const PATHS_TO_TABLE_BODY = [ + "//div[contains(@data-grid-id, 'customer_orders_grid')]", + "//table[contains(@class, 'data-grid')]", + "//tbody", + ]; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Store + */ + private $store; + + /** + * @var LayoutInterface + */ + private $layout; + + /** + * @var CurrencyInterface + */ + private $currency; + + /** + * @var TimezoneInterface + */ + private $timezone; + + /** + * @var Registry + */ + private $registry; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @var Orders + */ + private $ordersGridBlock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->store = $this->objectManager->get(Store::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->currency = $this->objectManager->get(CurrencyInterface::class); + $this->timezone = $this->objectManager->get(TimezoneInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->scopeConfig = $this->objectManager->get(ScopeConfigInterface::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister(RegistryConstants::CURRENT_CUSTOMER_ID); + parent::tearDown(); + } + + /** + * Assert that customer orders tab renders with message "We couldn't find any records." + * when customer doesn't have any orders. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testRenderBlockWithoutOrders(): void + { + $this->processCheckOrdersGridByCustomerId(1, 0); + } + + /** + * Assert that customer orders tab renders without message "We couldn't find any records." + * and contains rendered order item when customer has one order. + * + * @magentoDataFixture Magento/Sales/_files/order_with_customer.php + * + * @return void + */ + public function testRenderBlockWithOneOrder(): void + { + $this->processCheckOrdersGridByCustomerId(1, 1); + } + + /** + * Assert that customer orders tab renders without message "We couldn't find any records." + * and contains rendered orders items when customer has few orders. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Sales/_files/orders_with_customer.php + * + * @return void + */ + public function testRenderBlockWithFewOrders(): void + { + $this->processCheckOrdersGridByCustomerId(1, 5); + } + + /** + * Render orders grid and assert that all data rendered as expected. + * + * @param int $customerId + * @param int $expectedOrderCount + * @return void + */ + private function processCheckOrdersGridByCustomerId(int $customerId, int $expectedOrderCount): void + { + $this->registerCustomerId($customerId); + $ordersGridHtml = $this->getOrdersGridHtml(); + $orderItemsData = $this->getOrderGridItemsData(); + $this->assertOrdersCount($expectedOrderCount, $ordersGridHtml); + $this->assertIsEmptyGridMessageArrears($ordersGridHtml, $expectedOrderCount === 0); + $this->checkOrderItemsFields($orderItemsData, $ordersGridHtml); + } + + /** + * Add customer id to registry. + * + * @param int $customerId + * @return void + */ + private function registerCustomerId(int $customerId): void + { + $this->registry->unregister(RegistryConstants::CURRENT_CUSTOMER_ID); + $this->registry->register(RegistryConstants::CURRENT_CUSTOMER_ID, $customerId); + } + + /** + * Render customer orders tab. + * + * @return string + */ + private function getOrdersGridHtml(): string + { + $this->ordersGridBlock = $this->layout->createBlock(Orders::class); + + return $this->ordersGridBlock->toHtml(); + } + + /** + * Check that rendered html contains all provided order items. + * + * @param array $orderItemsData + * @param string $html + * @return void + */ + private function checkOrderItemsFields(array $orderItemsData, string $html): void + { + foreach ($orderItemsData as $itemOrder => $orderItemData) { + $this->assertViewOrderUrl($itemOrder, $orderItemData['order_id'], $html); + $this->assertReorderUrl($itemOrder, $orderItemData['order_id'], $html); + $this->assertStoreViewLabels($itemOrder, $orderItemData['store_view_labels'], $html); + unset($orderItemData['order_id'], $orderItemData['store_view_labels']); + $this->assertColumnsValues($itemOrder, $orderItemData, $html); + } + } + + /** + * Assert that field store_id contains all provided store codes. + * + * @param int $itemOrder + * @param array $storeViewLabels + * @param string $html + * @return void + */ + private function assertStoreViewLabels(int $itemOrder, array $storeViewLabels, string $html): void + { + if (empty($storeViewLabels)) { + return; + } + + $elementPaths = array_merge(self::PATHS_TO_TABLE_BODY, [ + "//tr[{$itemOrder}]", + "//td[contains(@class, 'store_id') and %s]", + ]); + $storeLabelsPaths = []; + foreach ($storeViewLabels as $labelIndex => $storeViewLabel) { + $storeLabelsPaths[] = "contains(text()[{$labelIndex}], '{$storeViewLabel}')"; + } + $checkStoreViewsXPath = sprintf(implode('', $elementPaths), implode(' and ', $storeLabelsPaths)); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($checkStoreViewsXPath, $html), + sprintf("Some store view label not found. Labels: %s. Html: %s", implode(', ', $storeViewLabels), $html) + ); + } + + /** + * Assert that columns values as expected. + * + * @param int $itemOrder + * @param array $columnsData + * @param string $html + * @return void + */ + private function assertColumnsValues(int $itemOrder, array $columnsData, string $html): void + { + $elementPaths = array_merge(self::PATHS_TO_TABLE_BODY, [ + "//tr[{$itemOrder}]", + "//td[contains(@class, '%s') and contains(text(), '%s')]", + ]); + $elementXPathTemplate = implode('', $elementPaths); + foreach ($columnsData as $columnName => $columnValue) { + $preparedXPath = sprintf($elementXPathTemplate, $columnName, $columnValue); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($preparedXPath, $html), + sprintf("Column %s doesn't have value %s. Html: %s", $columnName, $columnValue, $html) + ); + } + } + + /** + * Assert that rendered html contains URL to reorder by order id. + * + * @param int $itemOrder + * @param int $orderId + * @param string $html + * @return void + */ + private function assertReorderUrl(int $itemOrder, int $orderId, string $html): void + { + $urlLabel = (string)__('Reorder'); + $elementPaths = array_merge(self::PATHS_TO_TABLE_BODY, [ + "//tr[{$itemOrder}]", + "//td[contains(@class, 'action')]", + "//a[contains(@href, 'sales/order_create/reorder/order_id/$orderId') and contains(text(), '{$urlLabel}')]", + ]); + $reorderUrlXPath = implode('', $elementPaths); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($reorderUrlXPath, $html), + sprintf('Reorder URL is not as expected. Html: %s', $html) + ); + } + + /** + * Assert that rendered html contains URL to order view by order id. + * + * @param int $itemOrder + * @param int $orderId + * @param string $html + * @return void + */ + private function assertViewOrderUrl(int $itemOrder, int $orderId, string $html): void + { + $elementPaths = array_merge(self::PATHS_TO_TABLE_BODY, [ + "//tr[{$itemOrder}][contains(@title, 'sales/order/view/order_id/{$orderId}')]", + ]); + $viewOrderUrlXPath = implode('', $elementPaths); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($viewOrderUrlXPath, $html), + sprintf('URL to view order is not as expected. Html: %s', $html) + ); + } + + /** + * Assert that provided orders count and count in html are equals. + * + * @param int $expectedOrdersCount + * @param string $html + * @return void + */ + private function assertOrdersCount(int $expectedOrdersCount, string $html): void + { + $elementPaths = [ + "//div[contains(@data-grid-id, 'customer_orders_grid')]", + "//div[contains(@class, 'grid-header-row')]", + "//div[contains(@class, 'control-support-text')]", + sprintf("//span[contains(@id, 'grid-total-count') and contains(text(), '%s')]", $expectedOrdersCount), + ]; + $ordersCountXPath = implode('', $elementPaths); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($ordersCountXPath, $html), + sprintf('Provided count and count in html are not equals. Html: %s', $html) + ); + } + + /** + * Assert that grid contains or not contains message "We couldn't find any records.". + * + * @param string $html + * @param bool $isMessageAppears + * @return void + */ + private function assertIsEmptyGridMessageArrears(string $html, bool $isMessageAppears = false): void + { + $gridText = (string)__("We couldn't find any records."); + $elementPaths = array_merge(self::PATHS_TO_TABLE_BODY, [ + "//tr[contains(@class, 'tr-no-data')]", + "//td[contains(@class, 'empty-text') and contains(text(), \"{$gridText}\")]", + ]); + $emptyTextXPath = implode('', $elementPaths); + $this->assertEquals( + $isMessageAppears ? 1 : 0, + Xpath::getElementsCountForXpath($emptyTextXPath, $html), + sprintf('Message "We couldn\'t find any records." not found in html. Html: %s', $html) + ); + } + + /** + * Build array with rendered orders for check that all contained data appears. + * + * @return array + */ + private function getOrderGridItemsData(): array + { + $orders = []; + $orderNumber = 1; + /** @var Document $order */ + foreach ($this->ordersGridBlock->getCollection() as $order) { + $orderGrandTotal = $this->prepareGrandTotal( + $order->getData('grand_total'), + $order->getData('order_currency_code') + ); + $orders[$orderNumber] = [ + 'order_id' => (int)$order->getData(OrderInterface::ENTITY_ID), + 'increment_id' => $order->getData(OrderInterface::INCREMENT_ID), + 'created_at' => $this->prepareCreatedAtDate($order->getData(OrderInterface::CREATED_AT)), + 'billing_name' => $order->getData('billing_name'), + 'shipping_name' => $order->getData('shipping_name'), + 'grand_total' => $orderGrandTotal, + 'store_view_labels' => $this->prepareStoreViewLabels([$order->getData(OrderInterface::STORE_ID)]), + ]; + $orderNumber++; + } + + return $orders; + } + + /** + * Normalize created at date. + * + * @param string $createdAt + * @return string + */ + private function prepareCreatedAtDate(string $createdAt): string + { + $date = new \DateTime($createdAt); + + return $this->timezone->formatDateTime($date, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::MEDIUM); + } + + /** + * Normalize grand total. + * + * @param string $grandTotal + * @param string|null $orderCurrencyCode + * @return string + */ + private function prepareGrandTotal(string $grandTotal, ?string $orderCurrencyCode = null): string + { + $resultGrandTotal = sprintf("%f", (float)$grandTotal * 1.0); + $orderCurrencyCode = $orderCurrencyCode ?: + $this->scopeConfig->getValue(Currency::XML_PATH_CURRENCY_BASE, 'default'); + + return $this->currency->getCurrency($orderCurrencyCode)->toCurrency($resultGrandTotal); + } + + /** + * Normalize store ids. + * + * @param array $orderStoreIds + * @return array + */ + private function prepareStoreViewLabels(array $orderStoreIds): array + { + $result = []; + $storeStructure = $this->store->getStoresStructure(false, $orderStoreIds); + $textIndex = 0; + foreach ($storeStructure as $website) { + $textIndex++; + foreach ($website['children'] as $group) { + $textIndex++; + foreach ($group['children'] as $store) { + $textIndex++; + $result[$textIndex] = $store['label']; + } + } + } + + return $result; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php new file mode 100644 index 0000000000000..f500885a35ed2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Block\Form; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class checks login form view + * + * @magentoAppArea frontend + */ +class LoginTest extends TestCase +{ + private const EMAIL_LABEL_XPATH = "//label[@for='email']/span[contains(text(), 'Email')]"; + private const PASSWORD_LABEL_XPATH = "//label[@for='pass' ]/span[contains(text(), 'Password')]"; + private const EMAIL_INPUT_XPATH = "//input[@name ='login[username]' and contains(@data-validate,'required:true')" + . "and contains(@data-validate, \"'validate-email':true\")]"; + private const PASSWORD_INPUT_XPATH = "//input[@name='login[password]'" + . "and contains(@data-validate,'required:true')]"; + private const SIGN_IN_BUTTON_XPATH = "//button[@type='submit']/span[contains(text(), 'Sign In')]"; + private const FORGOT_PASSWORD_LINK_PATH = "//a[contains(@href, 'customer/account/forgotpassword')]" + . "/span[contains(text(), 'Forgot Your Password?')] "; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var Login */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Login::class); + $this->block->setTemplate('Magento_Customer::form/login.phtml'); + + parent::setUp(); + } + + /** + * @return void + */ + public function testLoginForm(): void + { + $result = $this->block->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::EMAIL_LABEL_XPATH, $result), + 'Email label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::PASSWORD_LABEL_XPATH, $result), + 'Password label does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::EMAIL_INPUT_XPATH, $result), + 'Email input does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::PASSWORD_INPUT_XPATH, $result), + 'Password input does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::SIGN_IN_BUTTON_XPATH, $result), + 'Sign in button does not exist on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::FORGOT_PASSWORD_LINK_PATH, $result), + 'Forgot password link does not exist on the page' + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/NewsletterTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/NewsletterTest.php new file mode 100644 index 0000000000000..8778a00e81499 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/NewsletterTest.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Block; + +use Magento\Customer\Model\Session; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class check newsletter subscription block behavior + * + * @see \Magento\Customer\Block\Newsletter + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Customer/_files/customer.php + */ +class NewsletterTest extends TestCase +{ + private const LABEL_XPATH = "//form[contains(@class, 'form-newsletter-manage')]" + . "//span[contains(text(), 'Subscription option')]"; + private const CHECKBOX_XPATH = "//form[contains(@class, 'form-newsletter-manage')]" + . "//input[@type='checkbox' and @name='is_subscribed']"; + private const CHECKBOX_TITLE_XPATH = "//form[contains(@class, 'form-newsletter-manage')]" + . "//label/span[contains(text(), 'General Subscription')]"; + private const SAVE_BUTTON_XPATH = "//form[contains(@class, 'form-newsletter-manage')]" + . "//button[@type='submit']/span[contains(text(), 'Save')]"; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var Newsletter */ + private $block; + + /** @var Session */ + private $customerSession; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->block = $this->layout->createBlock(Newsletter::class); + $this->customerSession = $this->objectManager->get(Session::class); + } + + /** + * @return void + */ + public function testSubscriptionCheckbox(): void + { + $this->customerSession->loginById(1); + $html = $this->block->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::LABEL_XPATH, $html), + 'Subscription label is not present on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::CHECKBOX_XPATH, $html), + 'Subscription checkbox is not present on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::CHECKBOX_TITLE_XPATH, $html), + 'Subscription checkbox label is not present on the page' + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::SAVE_BUTTON_XPATH, $html), + 'Subscription save button is not present on the page' + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/LoginPostTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/LoginPostTest.php new file mode 100644 index 0000000000000..80502833cb2d7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/LoginPostTest.php @@ -0,0 +1,171 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Account; + +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Url; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\Url\EncoderInterface; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks customer login action + * + * @see \Magento\Customer\Controller\Account\LoginPost + */ +class LoginPostTest extends AbstractController +{ + /** @var Session */ + private $session; + + /** @var EncoderInterface */ + private $urlEncoder; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->session = $this->_objectManager->get(Session::class); + $this->urlEncoder = $this->_objectManager->get(EncoderInterface::class); + } + + /** + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @dataProvider missingParametersDataProvider + * + * @param string|null $email + * @param string|null $password + * @param string $expectedErrorMessage + * @return void + */ + public function testLoginIncorrectParameters(?string $email, ?string $password, string $expectedErrorMessage): void + { + $this->prepareRequest($email, $password); + $this->dispatch('customer/account/loginPost'); + $this->assertSessionMessages( + $this->equalTo([(string)__($expectedErrorMessage)]), + MessageInterface::TYPE_ERROR + ); + } + + /** + * @return array + */ + public function missingParametersDataProvider(): array + { + return [ + 'missing_email' => [ + 'email' => null, + 'password' => 'password', + 'expected_error_message' => 'A login and a password are required.', + ], + 'missing_password' => [ + 'email' => 'customer@example.com', + 'password' => null, + 'expected_error_message' => 'A login and a password are required.', + ], + 'missing_both_parameters' => [ + 'email' => null, + 'password' => null, + 'expected_error_message' => 'A login and a password are required.', + ], + 'wrong_email' => [ + 'email' => 'wrongemail@example.com', + 'password' => 'password', + 'expected_error_message' => 'The account sign-in was incorrect or your account is disabled temporarily.' + . ' Please wait and try again later.', + ], + 'wrong_password' => [ + 'email' => 'customer@example.com', + 'password' => 'wrongpassword', + 'expected_error_message' => 'The account sign-in was incorrect or your account is disabled temporarily.' + . ' Please wait and try again later.', + ], + ]; + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer_confirmation_config_enable.php + * @magentoDataFixture Magento/Customer/_files/unconfirmed_customer.php + * + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @return void + */ + public function testLoginWithUnconfirmedPassword(): void + { + $this->markTestSkipped('Blocked by MC-31370.'); + $email = 'unconfirmedcustomer@example.com'; + $this->prepareRequest($email, 'Qwert12345'); + $this->dispatch('customer/account/loginPost'); + $this->assertEquals($email, $this->session->getUsername()); + $this->assertSessionMessages( + $this->equalTo([(string)__('This account is not confirmed. Click here to resend confirmation email.')]), + MessageInterface::TYPE_ERROR + ); + } + + /** + * @magentoConfigFixture current_store customer/startup/redirect_dashboard 0 + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testLoginWithRedirectToDashboardDisabled(): void + { + $this->prepareRequest('customer@example.com', 'password'); + $this->getRequest()->setParam(Url::REFERER_QUERY_PARAM_NAME, $this->urlEncoder->encode('test_redirect')); + $this->dispatch('customer/account/loginPost'); + $this->assertTrue($this->session->isLoggedIn()); + $this->assertRedirect($this->stringContains('test_redirect')); + } + + /** + * @magentoConfigFixture current_store customer/startup/redirect_dashboard 1 + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testLoginWithRedirectToDashboard(): void + { + $this->prepareRequest('customer@example.com', 'password'); + $this->getRequest()->setParam(Url::REFERER_QUERY_PARAM_NAME, $this->urlEncoder->encode('test_redirect')); + $this->dispatch('customer/account/loginPost'); + $this->assertTrue($this->session->isLoggedIn()); + $this->assertRedirect($this->stringContains('customer/account/')); + } + + /** + * Prepare request + * + * @param string|null $email + * @param string|null $password + * @return void + */ + private function prepareRequest(?string $email, ?string $password): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue([ + 'login' => [ + 'username' => $email, + 'password' => $password, + ], + ]); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index df4acf3acca91..9b0b53e11615f 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -8,13 +8,10 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Api\Data\CustomerInterface; -use Magento\Customer\Model\Account\Redirect; use Magento\Customer\Model\CustomerRegistry; use Magento\Customer\Model\Session; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\Config\Value; use Magento\Framework\App\Http; use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Data\Form\FormKey; @@ -26,10 +23,8 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Mail\Template\TransportBuilderMock; use Magento\TestFramework\Request; -use Magento\TestFramework\Response; use Magento\Theme\Controller\Result\MessagePlugin; use PHPUnit\Framework\Constraint\StringContains; -use Zend\Stdlib\Parameters; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -77,35 +72,6 @@ public function testIndexAction() $this->assertContains('Green str, 67', $body); } - /** - * @magentoDataFixture Magento/Customer/_files/customer_no_password.php - */ - public function testLoginWithIncorrectPassword() - { - $expectedMessage = 'The account sign-in was incorrect or your account is disabled temporarily. ' - . 'Please wait and try again later.'; - $this->getRequest() - ->setMethod('POST') - ->setPostValue( - [ - 'login' => [ - 'username' => 'customer@example.com', - 'password' => '123123q' - ] - ] - ); - - $this->dispatch('customer/account/loginPost'); - $this->assertRedirect($this->stringContains('customer/account/login')); - $this->assertSessionMessages( - $this->equalTo( - [ - $expectedMessage - ] - ) - ); - } - /** * Test sign up form displaying. */ @@ -132,35 +98,6 @@ public function testLogoutAction() $this->assertRedirect($this->stringContains('customer/account/logoutSuccess')); } - /** - * Test that forgot password email message displays special characters correctly. - * - * @codingStandardsIgnoreStart - * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 - * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template - * @magentoConfigFixture current_store customer/password/forgot_email_identity support - * @magentoConfigFixture current_store general/store_information/name Test special' characters - * @magentoConfigFixture current_store customer/captcha/enable 0 - * @magentoDataFixture Magento/Customer/_files/customer.php - * @codingStandardsIgnoreEnd - */ - public function testForgotPasswordEmailMessageWithSpecialCharacters() - { - $email = 'customer@example.com'; - - $this->getRequest()->setPostValue(['email' => $email]); - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/')); - - $subject = $this->transportBuilderMock->getSentMessage()->getSubject(); - $this->assertContains( - 'Test special\' characters', - $subject - ); - } - /** * @magentoDataFixture Magento/Customer/_files/customer.php */ @@ -397,56 +334,6 @@ public function testActiveUserConfirmationAction() ); } - /** - * @codingStandardsIgnoreStart - * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 - * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template - * @magentoConfigFixture current_store customer/password/forgot_email_identity support - * @magentoConfigFixture current_store customer/captcha/enable 0 - * @magentoDataFixture Magento/Customer/_files/customer.php - * @codingStandardsIgnoreEnd - */ - public function testForgotPasswordPostAction() - { - $email = 'customer@example.com'; - - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest()->setPostValue(['email' => $email]); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/')); - - $message = __( - 'If there is an account associated with %1 you will receive an email with a link to reset your password.', - $email - ); - $this->assertSessionMessages( - $this->equalTo([$message]), - MessageInterface::TYPE_SUCCESS - ); - } - - /** - * @magentoConfigFixture current_store customer/captcha/enable 0 - */ - public function testForgotPasswordPostWithBadEmailAction() - { - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest() - ->setPostValue( - [ - 'email' => 'bad@email', - ] - ); - - $this->dispatch('customer/account/forgotPasswordPost'); - $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); - $this->assertSessionMessages( - $this->equalTo(['The email address is incorrect. Verify the email address and try again.']), - MessageInterface::TYPE_ERROR - ); - } - /** * @magentoDataFixture Magento/Customer/_files/customer.php */ @@ -509,11 +396,12 @@ public function testEditAction() $this->assertEquals(200, $this->getResponse()->getHttpResponseCode(), $body); $this->assertContains('<div class="field field-name-firstname required">', $body); // Verify the password check box is not checked - $this->assertContains( - '<input type="checkbox" name="change_password" id="change-password" ' - . 'data-role="change-password" value="1" title="Change Password" class="checkbox" />', - $body - ); + $expectedString = <<<EXPECTED_HTML +<input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" + title="Change Password" + class="checkbox" /> +EXPECTED_HTML; + $this->assertContains($expectedString, $body); } /** @@ -529,12 +417,12 @@ public function testChangePasswordEditAction() $this->assertEquals(200, $this->getResponse()->getHttpResponseCode(), $body); $this->assertContains('<div class="field field-name-firstname required">', $body); // Verify the password check box is checked - $this->assertContains( - '<input type="checkbox" name="change_password" id="change-password" ' - . 'data-role="change-password" value="1" title="Change Password" checked="checked" ' - . 'class="checkbox" />', - $body - ); + $expectedString = <<<EXPECTED_HTML +<input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" + title="Change Password" + checked="checked" class="checkbox" /> +EXPECTED_HTML; + $this->assertContains($expectedString, $body); } /** @@ -719,35 +607,6 @@ public function testWrongConfirmationEditPostAction() ); } - /** - * Test redirect customer to account dashboard after logging in. - * - * @param bool|null $redirectDashboard - * @param string $redirectUrl - * @magentoDbIsolation enabled - * @magentoAppIsolation enabled - * @magentoDataFixture Magento/Customer/_files/customer.php - * @dataProvider loginPostRedirectDataProvider - */ - public function testLoginPostRedirect($redirectDashboard, string $redirectUrl) - { - if (isset($redirectDashboard)) { - $this->_objectManager->get(ScopeConfigInterface::class)->setValue( - 'customer/startup/redirect_dashboard', - $redirectDashboard - ); - } - $this->_objectManager->get(Redirect::class)->setRedirectCookie('test'); - $configValue = $this->_objectManager->create(Value::class); - $configValue->load('web/unsecure/base_url', 'path'); - $baseUrl = $configValue->getValue() ?: 'http://localhost/'; - $request = $this->prepareRequest(); - $app = $this->_objectManager->create(Http::class, ['_request' => $request]); - $response = $app->launch(); - $this->assertResponseRedirect($response, $baseUrl . $redirectUrl); - $this->assertTrue($this->_objectManager->get(Session::class)->isLoggedIn()); - } - /** * Register Customer with email confirmation. * @@ -994,20 +853,6 @@ private function resetRequest(): void $this->_request = null; } - /** - * Data provider for testLoginPostRedirect. - * - * @return array - */ - public function loginPostRedirectDataProvider() - { - return [ - [null, 'index.php/'], - [0, 'index.php/'], - [1, 'index.php/customer/account/'], - ]; - } - /** * @param string $email * @return void @@ -1076,44 +921,6 @@ private function getCustomerByEmail($email) return $customer; } - /** - * Prepare request for customer login. - * - * @return Request - */ - private function prepareRequest() - { - $post = new Parameters( - [ - 'form_key' => $this->_objectManager->get(FormKey::class)->getFormKey(), - 'login' => [ - 'username' => 'customer@example.com', - 'password' => 'password' - ] - ] - ); - $request = $this->getRequest(); - $formKey = $this->_objectManager->get(FormKey::class); - $request->setParam('form_key', $formKey->getFormKey()); - $request->setMethod(Request::METHOD_POST); - $request->setRequestUri('customer/account/loginPost/'); - $request->setPost($post); - return $request; - } - - /** - * Assert response is redirect. - * - * @param Response $response - * @param string $redirectUrl - * @return void - */ - private function assertResponseRedirect(Response $response, string $redirectUrl) - { - $this->assertTrue($response->isRedirect()); - $this->assertSame($redirectUrl, $response->getHeader('Location')->getUri()); - } - /** * Add new request info (request uri, path info, action name). * diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/Delete/DeleteAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/Delete/DeleteAddressTest.php new file mode 100644 index 0000000000000..86a443d7aa3e1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/Delete/DeleteAddressTest.php @@ -0,0 +1,217 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Address\Delete; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Request\Http; +use Magento\Framework\Escaper; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Message\MessageInterface; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Test cases related to check that customer address correctly deleted on frontend + * or wasn't deleted and proper error message appears. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * + * @see \Magento\Customer\Controller\Address\Delete::execute + */ +class DeleteAddressTest extends AbstractController +{ + /** + * @var Escaper + */ + private $escaper; + + /** + * @var Session + */ + private $customerSession; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->escaper = $this->_objectManager->get(Escaper::class); + $this->customerSession = $this->_objectManager->get(Session::class); + $this->addressRepository = $this->_objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class); + } + + /** + * Assert that customer address deleted successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @return void + */ + public function testSuccessDeleteExistCustomerAddress(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $customerAddresses = $customer->getAddresses() ?? []; + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $currentCustomerAddress */ + $currentCustomerAddress = reset($customerAddresses); + $this->customerSession->setCustomerId($customer->getId()); + $this->performAddressDeleteRequest((int)$currentCustomerAddress->getId()); + $this->checkRequestPerformedSuccessfully(); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertCount(0, $customer->getAddresses() ?? []); + try { + $this->addressRepository->getById((int)$currentCustomerAddress->getId()); + $this->fail('Customer address is not deleted.'); + } catch (LocalizedException $e) { + //Do nothing, this block mean that address deleted successfully from DB. + } + } + + /** + * Check that customer address will not be deleted if we don't pass address ID parameter. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @return void + */ + public function testDeleteWithoutParam(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $customerAddresses = $customer->getAddresses() ?? []; + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $currentCustomerAddress */ + $currentCustomerAddress = reset($customerAddresses); + $this->customerSession->setCustomerId($customer->getId()); + $this->performAddressDeleteRequest(); + $this->assertRedirect($this->stringContains('customer/address/index')); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertCount(1, $customer->getAddresses() ?? []); + $this->checkAddressWasntDeleted((int)$currentCustomerAddress->getId()); + } + + /** + * Check that customer address will not be deleted if customer id in address and in session are not equals. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * @magentoDataFixture Magento/Customer/_files/customer_with_uk_address.php + * + * @return void + */ + public function testDeleteDifferentCustomerAddress(): void + { + $firstCustomer = $this->customerRepository->get('customer@example.com'); + $customerAddresses = $firstCustomer->getAddresses() ?? []; + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $currentCustomerAddress */ + $currentCustomerAddress = reset($customerAddresses); + $this->customerSession->setCustomerId('1'); + $secondCustomer = $this->customerRepository->get('customer_uk_address@test.com'); + $secondCustomerAddresses = $secondCustomer->getAddresses() ?? []; + /** @var AddressInterface $secondCustomerAddress */ + $secondCustomerAddress = reset($secondCustomerAddresses); + $this->performAddressDeleteRequest((int)$secondCustomerAddress->getId()); + $this->checkRequestPerformedWithError(true); + $firstCustomer = $this->customerRepository->get('customer@example.com'); + $this->assertCount(1, $firstCustomer->getAddresses() ?? []); + $this->checkAddressWasntDeleted((int)$currentCustomerAddress->getId()); + } + + /** + * Check that error message appear if we try to delete non-exits address. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testDeleteNonExistAddress(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $this->customerSession->setCustomerId($customer->getId()); + $this->performAddressDeleteRequest(999); + $this->checkRequestPerformedWithError(); + } + + /** + * Perform delete request by provided address id. + * + * @param int|null $processAddressId + * @return void + */ + private function performAddressDeleteRequest(?int $processAddressId = null): void + { + $this->getRequest()->setMethod(Http::METHOD_POST); + if (null !== $processAddressId) { + $this->getRequest()->setPostValue(['id' => $processAddressId]); + } + $this->dispatch('customer/address/delete'); + } + + /** + * Check that delete address request performed successfully + * (proper success message and redirect to customer/address/index are appear). + * + * @return void + */ + private function checkRequestPerformedSuccessfully(): void + { + $this->assertRedirect($this->stringContains('customer/address/index')); + $this->assertSessionMessages( + $this->equalTo([(string)__('You deleted the address.')]), + MessageInterface::TYPE_SUCCESS + ); + } + + /** + * Check that delete address request performed with error. + * (proper error messages and redirect to customer/address/edit are appear). + * + * @param bool $isNeedEscapeMessage + * @return void + */ + private function checkRequestPerformedWithError(bool $isNeedEscapeMessage = false): void + { + $message = (string)__("We can't delete the address right now."); + if ($isNeedEscapeMessage) { + $message = $this->escaper->escapeHtml($message); + } + $this->assertSessionMessages($this->contains($message), MessageInterface::TYPE_ERROR); + } + + /** + * Assert that customer address wasn't deleted. + * + * @param int $addressId + * @return void + */ + private function checkAddressWasntDeleted(int $addressId): void + { + try { + $this->addressRepository->getById($addressId); + } catch (LocalizedException $e) { + $this->fail('Expects that customer address will not be deleted.'); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php new file mode 100644 index 0000000000000..1e152008043a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/CreateAddressTest.php @@ -0,0 +1,391 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Address\FormPost; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Api\Data\RegionInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Request\Http; +use Magento\Framework\Escaper; +use Magento\Framework\Message\MessageInterface; +use Magento\TestFramework\Directory\Model\GetRegionIdByName; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Test cases related to check that customer address correctly created from + * customer account page on frontend or wasn't create and proper error message appears. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * + * @see \Magento\Customer\Controller\Address\FormPost::execute + */ +class CreateAddressTest extends AbstractController +{ + /** + * POST static data for create customer address via controller on frontend. + */ + private const STATIC_POST_ADDRESS_DATA = [ + AddressInterface::TELEPHONE => '+380505282812', + AddressInterface::POSTCODE => 75477, + AddressInterface::COUNTRY_ID => 'US', + 'custom_region_name' => 'Alabama', + AddressInterface::CITY => 'CityM', + AddressInterface::STREET => [ + 'Green str, 67', + ], + AddressInterface::FIRSTNAME => 'John', + AddressInterface::LASTNAME => 'Smith', + ]; + + /** + * @var Escaper + */ + private $escaper; + + /** + * @var Session + */ + private $customerSession; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var GetRegionIdByName + */ + private $getRegionIdByName; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->escaper = $this->_objectManager->get(Escaper::class); + $this->customerSession = $this->_objectManager->get(Session::class); + $this->customerRegistry = $this->_objectManager->get(CustomerRegistry::class); + $this->getRegionIdByName = $this->_objectManager->get(GetRegionIdByName::class); + $this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class); + $this->customerSession->setCustomerId('5'); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->setCustomerId(null); + $this->customerRegistry->removeByEmail('customer5@example.com'); + parent::tearDown(); + } + + /** + * Assert that default or non-default customer address successfully created via controller on frontend. + * + * @dataProvider postDataForSuccessCreateDefaultAddressDataProvider + * + * @param array $postData + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @return void + */ + public function testAddressSuccessfullyCreatedAsDefaultForCustomer( + array $postData, + bool $isShippingDefault, + bool $isBillingDefault + ): void { + $customer = $this->customerRepository->get('customer5@example.com'); + $this->assertNull($customer->getDefaultShipping(), 'Customer already have default shipping address'); + $this->assertNull($customer->getDefaultBilling(), 'Customer already have default billing address'); + $this->assertEmpty($customer->getAddresses(), 'Customer already has address'); + $this->performRequestWithData($postData); + $this->checkRequestPerformedSuccessfully(); + $customer = $this->customerRepository->get('customer5@example.com'); + $customerAddresses = $customer->getAddresses(); + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $address */ + $address = reset($customerAddresses); + $expectedShippingId = $isShippingDefault ? $address->getId() : null; + $expectedBillingId = $isBillingDefault ? $address->getId() : null; + $this->assertEquals($expectedShippingId, $customer->getDefaultShipping()); + $this->assertEquals($expectedBillingId, $customer->getDefaultBilling()); + } + + /** + * Data provider which contain proper POST data for create default or non-default customer address. + * + * @return array + */ + public function postDataForSuccessCreateDefaultAddressDataProvider(): array + { + return [ + 'any_addresses_are_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 0, AddressInterface::DEFAULT_BILLING => 0] + ), + false, + false, + ], + 'shipping_address_is_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 1, AddressInterface::DEFAULT_BILLING => 0] + ), + true, + false, + ], + 'billing_address_is_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 0, AddressInterface::DEFAULT_BILLING => 1] + ), + false, + true, + ], + 'all_addresses_are_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 1, AddressInterface::DEFAULT_BILLING => 1] + ), + true, + true, + ], + ]; + } + + /** + * Assert that customer address successfully created via controller on frontend. + * + * @dataProvider postDataForSuccessCreateAddressDataProvider + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testAddressSuccessfullyCreatedForCustomer(array $postData, array $expectedData): void + { + if (isset($expectedData['custom_region_name'])) { + $expectedData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $expectedData['custom_region_name'], + $expectedData[AddressInterface::COUNTRY_ID] + ); + unset($expectedData['custom_region_name']); + } + $this->performRequestWithData($postData); + $this->checkRequestPerformedSuccessfully(); + $customer = $this->customerRepository->get('customer5@example.com'); + $customerAddresses = $customer->getAddresses(); + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $address */ + $address = reset($customerAddresses); + $createdAddressData = $address->__toArray(); + foreach ($expectedData as $fieldCode => $expectedValue) { + $this->assertArrayHasKey($fieldCode, $createdAddressData, "Field $fieldCode wasn't found."); + $this->assertEquals($expectedValue, $createdAddressData[$fieldCode]); + } + } + + /** + * Data provider which contain proper POST data for create customer address. + * + * @return array + */ + public function postDataForSuccessCreateAddressDataProvider(): array + { + return [ + 'required_fields_valid_data' => [ + self::STATIC_POST_ADDRESS_DATA, + [ + AddressInterface::TELEPHONE => '+380505282812', + AddressInterface::COUNTRY_ID => 'US', + AddressInterface::POSTCODE => 75477, + 'custom_region_name' => 'Alabama', + AddressInterface::FIRSTNAME => 'John', + AddressInterface::LASTNAME => 'Smith', + AddressInterface::STREET => ['Green str, 67'], + AddressInterface::CITY => 'CityM', + ], + ], + 'required_field_empty_postcode_for_uk' => [ + array_replace( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::POSTCODE => '', AddressInterface::COUNTRY_ID => 'GB'] + ), + [ + AddressInterface::COUNTRY_ID => 'GB', + AddressInterface::POSTCODE => null, + ], + ], + 'required_field_empty_region_id_for_ua' => [ + array_replace( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::REGION_ID => '', AddressInterface::COUNTRY_ID => 'UA'] + ), + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION => [ + RegionInterface::REGION => null, + RegionInterface::REGION_CODE => null, + RegionInterface::REGION_ID => 0, + ], + ], + ], + 'required_field_street_as_array' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), + [AddressInterface::STREET => ['Green str, 67']], + ], + 'field_company_name' => [ + array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::VAT_ID => 'My VAT number']), + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that customer address wasn't created via controller on frontend + * when POST data broken. + * + * @dataProvider postDataForCreateAddressWithErrorDataProvider + * + * @param array $postData + * @param array $expectedSessionMessages + * @return void + */ + public function testAddressWasntCreatedForCustomer(array $postData, array $expectedSessionMessages): void + { + $this->performRequestWithData($postData); + $this->checkRequestPerformedWithInputValidationErrors($expectedSessionMessages); + } + + /** + * Data provider which contain broken POST data for create customer address with error. + * + * @return array + */ + public function postDataForCreateAddressWithErrorDataProvider(): array + { + return [ + 'empty_post_data' => [ + [], + [ + 'One or more input exceptions have occurred.', + '"firstname" is required. Enter and try again.', + '"lastname" is required. Enter and try again.', + '"street" is required. Enter and try again.', + '"city" is required. Enter and try again.', + '"telephone" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', + '"countryId" is required. Enter and try again.', + ] + ], + 'required_field_empty_telephone' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::TELEPHONE => '']), + ['"telephone" is required. Enter and try again.'], + ], + 'required_field_empty_postcode_for_us' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::POSTCODE => '']), + ['"postcode" is required. Enter and try again.'], + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::REGION_ID => '']), +// ['"regionId" is required. Enter and try again.'], +// ], + 'required_field_empty_firstname' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::FIRSTNAME => '']), + ['"firstname" is required. Enter and try again.'], + ], + 'required_field_empty_lastname' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::LASTNAME => '']), + ['"lastname" is required. Enter and try again.'], + ], + 'required_field_empty_street_as_string' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => '']), + ['"street" is required. Enter and try again.'], + ], + 'required_field_empty_street_as_array' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => []]), + ['"street" is required. Enter and try again.'], + ], + 'required_field_empty_city' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::CITY => '']), + ['"city" is required. Enter and try again.'], + ], + ]; + } + + /** + * Perform request with provided POST data. + * + * @param array $postData + * @return void + */ + private function performRequestWithData(array $postData): void + { + if (isset($postData['custom_region_name'])) { + $postData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $postData['custom_region_name'], + $postData[AddressInterface::COUNTRY_ID] + ); + unset($postData['custom_region_name']); + } + + $this->getRequest()->setPostValue($postData)->setMethod(Http::METHOD_POST); + $this->dispatch('customer/address/formPost'); + } + + /** + * Check that save address request performed successfully + * (proper success message and redirect to customer/address/index are appear). + * + * @return void + */ + private function checkRequestPerformedSuccessfully(): void + { + $this->assertRedirect($this->stringContains('customer/address/index')); + $this->assertSessionMessages( + $this->equalTo([(string)__('You saved the address.')]), + MessageInterface::TYPE_SUCCESS + ); + } + + /** + * Check that save address request performed with input validation errors + * (proper error messages and redirect to customer/address/edit are appear). + * + * @param array $expectedSessionMessages + * @return void + */ + private function checkRequestPerformedWithInputValidationErrors(array $expectedSessionMessages): void + { + $this->assertRedirect($this->stringContains('customer/address/edit')); + foreach ($expectedSessionMessages as $expectedMessage) { + $this->assertSessionMessages( + $this->contains($this->escaper->escapeHtml((string)__($expectedMessage))), + MessageInterface::TYPE_ERROR + ); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php new file mode 100644 index 0000000000000..fb18cc45511c8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Address/FormPost/UpdateAddressTest.php @@ -0,0 +1,403 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Address\FormPost; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Api\Data\RegionInterface; +use Magento\Customer\Model\AddressRegistry; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\Session; +use Magento\Framework\App\Request\Http; +use Magento\Framework\Escaper; +use Magento\Framework\Message\MessageInterface; +use Magento\TestFramework\Directory\Model\GetRegionIdByName; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Test cases related to check that customer address correctly updated from + * customer account page on frontend or wasn't updated and proper error message appears. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * + * @see \Magento\Customer\Controller\Address\FormPost::execute + */ +class UpdateAddressTest extends AbstractController +{ + /** + * POST static data for update customer address via controller on frontend. + */ + private const STATIC_POST_ADDRESS_DATA = [ + AddressInterface::TELEPHONE => 9548642, + AddressInterface::POSTCODE => 95556, + AddressInterface::COUNTRY_ID => 'US', + 'custom_region_name' => 'Arkansas', + AddressInterface::CITY => 'Mukachevo', + AddressInterface::STREET => [ + 'Yellow str, 228', + ], + AddressInterface::FIRSTNAME => 'Foma', + AddressInterface::LASTNAME => 'Kiniaev', + ]; + + /** + * @var Escaper + */ + private $escaper; + + /** + * @var Session + */ + private $customerSession; + + /** + * @var AddressRegistry + */ + private $addressRegistry; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var GetRegionIdByName + */ + private $getRegionIdByName; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var array + */ + private $processedAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->escaper = $this->_objectManager->get(Escaper::class); + $this->customerSession = $this->_objectManager->get(Session::class); + $this->addressRegistry = $this->_objectManager->get(AddressRegistry::class); + $this->customerRegistry = $this->_objectManager->get(CustomerRegistry::class); + $this->getRegionIdByName = $this->_objectManager->get(GetRegionIdByName::class); + $this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class); + $this->customerSession->setCustomerId('1'); + $this->processedAddressesIds[] = 1; + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->setCustomerId(null); + $this->customerRegistry->removeByEmail('customer@example.com'); + foreach ($this->processedAddressesIds as $addressesId) { + $this->addressRegistry->remove($addressesId); + } + parent::tearDown(); + } + + /** + * Assert that default customer address successfully changed via controller on frontend. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php + * + * @dataProvider postDataForSuccessCreateDefaultAddressDataProvider + * + * @param array $postData + * @param int $expectedShippingId + * @param int $expectedBillingId + * @return void + */ + public function testAddressSuccessfullyCreatedAsDefaultForCustomer( + array $postData, + int $expectedShippingId, + int $expectedBillingId + ): void { + $this->processedAddressesIds = [1, 2]; + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping(), "Customer doesn't have shipping address"); + $this->assertEquals(1, $customer->getDefaultBilling(), "Customer doesn't have billing address"); + $this->performRequestWithData($postData, 2); + $this->checkRequestPerformedSuccessfully(); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals($expectedShippingId, $customer->getDefaultShipping()); + $this->assertEquals($expectedBillingId, $customer->getDefaultBilling()); + } + + /** + * Data provider which contain proper POST data for change default customer address. + * + * @return array + */ + public function postDataForSuccessCreateDefaultAddressDataProvider(): array + { + return [ + 'any_addresses_are_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 2, AddressInterface::DEFAULT_BILLING => 2] + ), + 2, + 2, + ], + 'shipping_address_is_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_BILLING => 2] + ), + 1, + 2, + ], + 'billing_address_is_default' => [ + array_merge( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::DEFAULT_SHIPPING => 2] + ), + 2, + 1, + ], + ]; + } + + /** + * Assert that customer address successfully updated via controller on frontend. + * + * @dataProvider postDataForSuccessUpdateAddressDataProvider + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testAddressSuccessfullyUpdatedForCustomer(array $postData, array $expectedData): void + { + if (isset($expectedData['custom_region_name'])) { + $expectedData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $expectedData['custom_region_name'], + $expectedData[AddressInterface::COUNTRY_ID] + ); + unset($expectedData['custom_region_name']); + } + $this->performRequestWithData($postData, 1); + $this->checkRequestPerformedSuccessfully(); + $customer = $this->customerRepository->get('customer@example.com'); + $customerAddresses = $customer->getAddresses(); + $this->assertCount(1, $customerAddresses); + /** @var AddressInterface $address */ + $address = reset($customerAddresses); + $createdAddressData = $address->__toArray(); + foreach ($expectedData as $fieldCode => $expectedValue) { + if (null === $expectedValue) { + $this->assertArrayNotHasKey($fieldCode, $createdAddressData); + continue; + } + $this->assertArrayHasKey($fieldCode, $createdAddressData, "Field $fieldCode wasn't found."); + $this->assertEquals($expectedValue, $createdAddressData[$fieldCode]); + } + } + + /** + * Data provider which contain proper POST data for update customer address. + * + * @return array + */ + public function postDataForSuccessUpdateAddressDataProvider(): array + { + return [ + 'required_fields_valid_data' => [ + self::STATIC_POST_ADDRESS_DATA, + [ + AddressInterface::TELEPHONE => 9548642, + AddressInterface::COUNTRY_ID => 'US', + AddressInterface::POSTCODE => 95556, + 'custom_region_name' => 'Arkansas', + AddressInterface::FIRSTNAME => 'Foma', + AddressInterface::LASTNAME => 'Kiniaev', + AddressInterface::STREET => ['Yellow str, 228'], + AddressInterface::CITY => 'Mukachevo', + ], + ], + 'required_field_empty_postcode_for_uk' => [ + array_replace( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::POSTCODE => '', AddressInterface::COUNTRY_ID => 'GB'] + ), + [ + AddressInterface::COUNTRY_ID => 'GB', + AddressInterface::POSTCODE => null, + ], + ], + 'required_field_empty_region_id_for_ua' => [ + array_replace( + self::STATIC_POST_ADDRESS_DATA, + [AddressInterface::REGION_ID => '', AddressInterface::COUNTRY_ID => 'UA'] + ), + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION => [ + RegionInterface::REGION => null, + RegionInterface::REGION_CODE => null, + RegionInterface::REGION_ID => 0, + ], + ], + ], + 'required_field_street_as_array' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), + [AddressInterface::STREET => ['Green str, 67']], + ], + 'field_company_name' => [ + array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + array_merge(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::VAT_ID => 'My VAT number']), + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that customer address wasn't updated via controller on frontend + * when POST data broken. + * + * @dataProvider postDataForUpdateAddressWithErrorDataProvider + * + * @param array $postData + * @param array $expectedSessionMessages + * @return void + */ + public function testAddressWasntUpdatedForCustomer(array $postData, array $expectedSessionMessages): void + { + $this->performRequestWithData($postData, 1); + $this->checkRequestPerformedWithInputValidationErrors($expectedSessionMessages); + } + + /** + * Data provider which contain broken POST data for update customer address with error. + * + * @return array + */ + public function postDataForUpdateAddressWithErrorDataProvider(): array + { + return [ + 'empty_post_data' => [ + [], + [ + 'One or more input exceptions have occurred.', + '"firstname" is required. Enter and try again.', + '"lastname" is required. Enter and try again.', + '"street" is required. Enter and try again.', + '"city" is required. Enter and try again.', + '"telephone" is required. Enter and try again.', + '"postcode" is required. Enter and try again.', + '"countryId" is required. Enter and try again.', + ] + ], + 'required_field_empty_telephone' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::TELEPHONE => '']), + ['"telephone" is required. Enter and try again.'], + ], + 'required_field_empty_postcode_for_us' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::POSTCODE => '']), + ['"postcode" is required. Enter and try again.'], + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::REGION_ID => '']), +// ['"regionId" is required. Enter and try again.'], +// ], + 'required_field_empty_firstname' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::FIRSTNAME => '']), + ['"firstname" is required. Enter and try again.'], + ], + 'required_field_empty_lastname' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::LASTNAME => '']), + ['"lastname" is required. Enter and try again.'], + ], + 'required_field_empty_street_as_string' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => '']), + ['"street" is required. Enter and try again.'], + ], + 'required_field_empty_street_as_array' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::STREET => []]), + ['"street" is required. Enter and try again.'], + ], + 'required_field_empty_city' => [ + array_replace(self::STATIC_POST_ADDRESS_DATA, [AddressInterface::CITY => '']), + ['"city" is required. Enter and try again.'], + ], + ]; + } + + /** + * Perform request with provided POST data. + * + * @param array $postData + * @param int $processAddressId + * @return void + */ + private function performRequestWithData(array $postData, int $processAddressId): void + { + $postData[AddressInterface::ID] = $processAddressId; + if (isset($postData['custom_region_name'])) { + $postData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $postData['custom_region_name'], + $postData[AddressInterface::COUNTRY_ID] + ); + unset($postData['custom_region_name']); + } + + $this->getRequest()->setPostValue($postData)->setMethod(Http::METHOD_POST); + $this->dispatch('customer/address/formPost'); + } + + /** + * Check that save address request performed successfully + * (proper success message and redirect to customer/address/index are appear). + * + * @return void + */ + private function checkRequestPerformedSuccessfully(): void + { + $this->assertRedirect($this->stringContains('customer/address/index')); + $this->assertSessionMessages( + $this->equalTo([(string)__('You saved the address.')]), + MessageInterface::TYPE_SUCCESS + ); + } + + /** + * Check that save address request performed with input validation errors + * (proper error messages and redirect to customer/address/edit are appear). + * + * @param array $expectedSessionMessages + * @return void + */ + private function checkRequestPerformedWithInputValidationErrors(array $expectedSessionMessages): void + { + $this->assertRedirect($this->stringContains('customer/address/edit')); + foreach ($expectedSessionMessages as $expectedMessage) { + $this->assertSessionMessages( + $this->contains($this->escaper->escapeHtml((string)__($expectedMessage))), + MessageInterface::TYPE_ERROR + ); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/InlineEditTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/InlineEditTest.php new file mode 100644 index 0000000000000..9879c8300f66c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/InlineEditTest.php @@ -0,0 +1,153 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Adminhtml\Index; + +use Magento\Customer\Api\CustomerMetadataInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Eav\Model\AttributeRepository; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Test inline edit action on customers grid. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + */ +class InlineEditTest extends AbstractBackendController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var CustomerRepositoryInterface */ + private $customerRepository; + + /** @var SerializerInterface */ + private $json; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** @var AttributeRepository */ + private $attributeRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + $this->json = $this->objectManager->get(SerializerInterface::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + $this->attributeRepository = $this->objectManager->get(AttributeRepository::class); + } + + /** + * @magentoDataFixture Magento/Customer/_files/two_customers.php + * + * @return void + */ + public function testInlineEditAction(): void + { + $firstCustomer = $this->customerRepository->get('customer@example.com'); + $secondCustomer = $this->customerRepository->get('customer_two@example.com'); + $defaultWebsiteId = $this->websiteRepository->get('base')->getId(); + $genderId = $this->attributeRepository->get(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'gender') + ->getSource()->getOptionId('Male'); + $params = [ + 'items' => [ + $firstCustomer->getId() => [ + CustomerInterface::EMAIL => 'updated_customer@example.com', + CustomerInterface::GROUP_ID => 2, + CustomerInterface::WEBSITE_ID => $defaultWebsiteId, + CustomerInterface::TAXVAT => 123123, + CustomerInterface::GENDER => $genderId, + ], + $secondCustomer->getId() => [ + CustomerInterface::EMAIL => 'updated_customer_two@example.com', + CustomerInterface::GROUP_ID => 3, + CustomerInterface::WEBSITE_ID => $defaultWebsiteId, + CustomerInterface::TAXVAT => 456456, + CustomerInterface::GENDER => $genderId, + ], + ], + 'isAjax' => true, + ]; + $actual = $this->performInlineEditRequest($params); + $this->assertEmpty($actual['messages']); + $this->assertFalse($actual['error']); + $this->assertCustomersData($params); + } + + /** + * @dataProvider inlineEditParametersDataProvider + * + * @param array $params + * @return void + */ + public function testInlineEditWithWrongParams(array $params): void + { + $actual = $this->performInlineEditRequest($params); + $this->assertEquals([(string)__('Please correct the data sent.')], $actual['messages']); + $this->assertTrue($actual['error']); + } + + /** + * @return array + */ + public function inlineEditParametersDataProvider(): array + { + return [ + [ + 'items' => [], + 'isAjax' => true, + ], + [ + 'items' => [], + ], + ]; + } + + /** + * Perform inline edit request. + * + * @param array $params + * @return array + */ + private function performInlineEditRequest(array $params): array + { + $this->getRequest()->setParams($params)->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('backend/customer/index/inlineEdit'); + + return $this->json->unserialize($this->getResponse()->getBody()); + } + + /** + * Assert customers data. + * + * @param array $data + * @return void + */ + private function assertCustomersData(array $data): void + { + foreach ($data['items'] as $customerId => $expectedData) { + $customerData = $this->customerRepository->getById($customerId)->__toArray(); + foreach ($expectedData as $key => $value) { + $this->assertEquals($value, $customerData[$key]); + } + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribeTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribeTest.php new file mode 100644 index 0000000000000..586d06eb42b24 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribeTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Adminhtml\Index; + +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory; +use Magento\Newsletter\Model\Subscriber; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Test mass subscribe action on customers grid. + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + */ +class MassUnsubscribeTest extends AbstractBackendController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var CustomerRepositoryInterface */ + private $customerRepository; + + /** @var CollectionFactory */ + private $subscriberCollectionFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->subscriberCollectionFactory = $this->objectManager->get(CollectionFactory::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + } + + /** + * @magentoDataFixture Magento/Newsletter/_files/three_subscribers.php + * + * @return void + */ + public function testMassUnsubscribeAction(): void + { + $params = [ + 'selected' => [1, 2, 3], + 'namespace' => 'customer_listing', + ]; + $this->getRequest()->setParams($params)->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('backend/customer/index/massUnsubscribe'); + $this->assertRedirect($this->stringContains('backend/customer/index/index')); + $this->assertSessionMessages( + $this->equalTo([(string)__('A total of 3 record(s) were updated.')]), + MessageInterface::TYPE_SUCCESS + ); + $emails = ['customer@search.example.com', 'customer2@search.example.com', 'customer3@search.example.com']; + $collection = $this->subscriberCollectionFactory->create()->addFieldToFilter('subscriber_email', $emails) + ->addFieldToSelect('subscriber_status'); + $this->assertCount(3, $collection); + foreach ($collection as $subscriber) { + $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getData('subscriber_status')); + } + } + + /** + * @return void + */ + public function testMassSubscriberActionNoSelection(): void + { + $params = [ + 'namespace' => 'customer_listing', + ]; + $this->getRequest()->setParams($params)->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('backend/customer/index/massUnsubscribe'); + $this->assertRedirect($this->stringContains('backend/customer/index/index')); + $this->assertSessionMessages( + $this->equalTo([(string)__('An item needs to be selected. Select and try again.')]), + MessageInterface::TYPE_ERROR + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php new file mode 100644 index 0000000000000..bbaf55494294e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller; + +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Customer as CustomerResource; +use Magento\Customer\Model\Session; +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks password forgot scenarios + * + * @magentoDbIsolation enabled + */ +class CreatePasswordTest extends AbstractController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Session */ + private $session; + + /** @var LayoutInterface */ + private $layout; + + /** @var Random */ + private $random; + + /** @var CustomerResource */ + private $customerResource; + + /** @var CustomerRegistry */ + private $customerRegistry; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** @var int */ + private $customerId; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->session = $this->objectManager->get(Session::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->random = $this->objectManager->get(Random::class); + $this->customerResource = $this->objectManager->get(CustomerResource::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerRegistry->remove($this->customerId); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer_with_website.php + * + * @return void + */ + public function testCreatePassword(): void + { + $defaultWebsite = $this->websiteRepository->get('base')->getId(); + $customer = $this->customerRegistry->retrieveByEmail('john.doe@magento.com', $defaultWebsite); + $this->customerId = $customer->getId(); + $token = $this->random->getUniqueHash(); + $customer->changeResetPasswordLinkToken($token); + $customer->setData('confirmation', 'confirmation'); + $this->customerResource->save($customer); + $this->session->setRpToken($token); + $this->session->setRpCustomerId($customer->getId()); + $this->dispatch('customer/account/createPassword'); + $block = $this->layout->getBlock('resetPassword'); + $this->assertEquals($token, $block->getResetPasswordLinkToken()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php new file mode 100644 index 0000000000000..8bfe3b5524487 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php @@ -0,0 +1,137 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller; + +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Mail\Template\TransportBuilderMock; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks password forgot scenarios + * + * @see \Magento\Customer\Controller\Account\ForgotPasswordPost + * @magentoDbIsolation enabled + */ +class ForgotPasswordPostTest extends AbstractController +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var TransportBuilderMock */ + private $transportBuilderMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->transportBuilderMock = $this->objectManager->get(TransportBuilderMock::class); + } + + /** + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @return void + */ + public function testWithoutEmail(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => '']); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertSessionMessages( + $this->equalTo([(string)__('Please enter your email.')]), + MessageInterface::TYPE_ERROR + ); + $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); + } + + /** + * Test that forgot password email message displays special characters correctly. + * + * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 + * @codingStandardsIgnoreStart + * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template + * @codingStandardsIgnoreEnd + * @magentoConfigFixture current_store customer/password/forgot_email_identity support + * @magentoConfigFixture current_store general/store_information/name Test special' characters + * @magentoConfigFixture current_store customer/captcha/enable 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPasswordEmailMessageWithSpecialCharacters(): void + { + $email = 'customer@example.com'; + $this->getRequest()->setPostValue(['email' => $email]); + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/')); + $this->assertSuccessSessionMessage($email); + $subject = $this->transportBuilderMock->getSentMessage()->getSubject(); + $this->assertContains('Test special\' characters', $subject); + } + + /** + * @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0 + * @codingStandardsIgnoreStart + * @magentoConfigFixture current_store customer/password/forgot_email_template customer_password_forgot_email_template + * @codingStandardsIgnoreEnd + * @magentoConfigFixture current_store customer/password/forgot_email_identity support + * @magentoConfigFixture current_store customer/captcha/enable 0 + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPasswordPostAction(): void + { + $email = 'customer@example.com'; + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => $email]); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/')); + $this->assertSuccessSessionMessage($email); + } + + /** + * @magentoConfigFixture current_store customer/captcha/enable 0 + * + * @return void + */ + public function testForgotPasswordPostWithBadEmailAction(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => 'bad@email']); + $this->dispatch('customer/account/forgotPasswordPost'); + $this->assertRedirect($this->stringContains('customer/account/forgotpassword')); + $this->assertSessionMessages( + $this->equalTo(['The email address is incorrect. Verify the email address and try again.']), + MessageInterface::TYPE_ERROR + ); + } + + /** + * Assert success session message + * + * @param string $email + * @return void + */ + private function assertSuccessSessionMessage(string $email): void + { + $message = __( + 'If there is an account associated with %1 you will receive an email with a link to reset your password.', + $email + ); + $this->assertSessionMessages($this->equalTo([$message]), MessageInterface::TYPE_SUCCESS); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php index 3db22b8379850..0869832091fec 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Section/LoadTest.php @@ -3,19 +3,104 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Customer\Controller\Section; -class LoadTest extends \Magento\TestFramework\TestCase\AbstractController +use Magento\Customer\Model\Session; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\TestCase\AbstractController; +use Magento\Framework\Escaper; + +/** + * Load customer data test class. + * + * @magentoDbIsolation enabled + * @magentoAppArea frontend + */ +class LoadTest extends AbstractController { - public function testLoadInvalidSection() + /** @var Session */ + private $customerSession; + + /** @var SerializerInterface */ + private $json; + + /** @var Escaper */ + private $escaper; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->customerSession = $this->_objectManager->get(Session::class); + $this->json = $this->_objectManager->get(SerializerInterface::class); + $this->escaper = $this->_objectManager->get(Escaper::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->setCustomerId(null); + + parent::tearDown(); + } + + /** + * @return void + */ + public function testLoadInvalidSection(): void { - $expected = [ - 'message' => 'The "section<invalid" section source isn't supported.', - ]; + $message = $this->escaper->escapeHtml('The "section<invalid" section source isn\'t supported.'); + $expected = ['message' => $message]; $this->dispatch( '/customer/section/load/?sections=section<invalid&force_new_section_timestamp=false&_=147066166394' ); - self::assertEquals(json_encode($expected), $this->getResponse()->getBody()); + $this->assertEquals($this->json->serialize($expected), $this->getResponse()->getBody()); + } + + /** + * @magentoConfigFixture current_store wishlist/wishlist_link/use_qty 1 + * @magentoDataFixture Magento/Wishlist/_files/wishlist_with_product_qty_three.php + * + * @return void + */ + public function testWishListCounterUseQty(): void + { + $this->customerSession->setCustomerId(1); + $response = $this->performWishListSectionRequest(); + $this->assertEquals('3 items', $response['wishlist']['counter']); + } + + /** + * @magentoConfigFixture current_store wishlist/wishlist_link/use_qty 0 + * @magentoDataFixture Magento/Wishlist/_files/wishlist_with_product_qty_three.php + * + * @return void + */ + public function testWishListCounterNotUseQty(): void + { + $this->customerSession->setCustomerId(1); + $response = $this->performWishListSectionRequest(); + $this->assertEquals('1 item', $response['wishlist']['counter']); + } + + /** + * Perform wish list section request. + * + * @return array + */ + private function performWishListSectionRequest(): array + { + $this->getRequest()->setParam('sections', 'wishlist')->setMethod(HttpRequest::METHOD_GET); + $this->dispatch('customer/section/load'); + + return $this->json->unserialize($this->getResponse()->getBody()); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php new file mode 100644 index 0000000000000..03473e9247c51 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\AccountManagement; + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Customer\Api\Data\CustomerInterfaceFactory; +use Magento\Framework\Api\DataObjectHelper; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Math\Random; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Validator\Exception; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for customer creation via customer account management service. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + */ +class CreateAccountTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var AccountManagementInterface + */ + private $accountManagement; + + /** + * @var CustomerInterfaceFactory + */ + private $customerFactory; + + /** + * @var DataObjectHelper + */ + private $dataObjectHelper; + + /** + * @var array + */ + private $defaultCustomerData = [ + 'email' => 'customer@example.com', + 'firstname' => 'First name', + 'lastname' => 'Last name', + ]; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->accountManagement = $this->objectManager->get(AccountManagementInterface::class); + $this->customerFactory = $this->objectManager->get(CustomerInterfaceFactory::class); + $this->dataObjectHelper = $this->objectManager->create(DataObjectHelper::class); + parent::setUp(); + } + + /** + * @dataProvider createInvalidAccountDataProvider + * @param array $customerData + * @param string $password + * @param string $errorType + * @param string $errorMessage + * @return void + */ + public function testCreateAccountWithInvalidFields( + array $customerData, + string $password, + string $errorType, + array $errorMessage + ): void { + $data = array_merge($this->defaultCustomerData, $customerData); + $customerEntity = $this->customerFactory->create(); + $this->dataObjectHelper->populateWithArray($customerEntity, $data, CustomerInterface::class); + $this->expectException($errorType); + $this->expectExceptionMessage((string)__(...$errorMessage)); + $this->accountManagement->createAccount($customerEntity, $password); + } + + /** + * @return array + */ + public function createInvalidAccountDataProvider(): array + { + return [ + 'empty_firstname' => [ + 'customer_data' => ['firstname' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is a required value.', 'First Name'], + ], + 'empty_lastname' => [ + 'customer_data' => ['lastname' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is a required value.', 'Last Name'], + ], + 'empty_email' => [ + 'customer_data' => ['email' => ''], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['The customer email is missing. Enter and try again.'], + ], + 'invalid_email' => [ + 'customer_data' => ['email' => 'zxczxczxc'], + 'password' => '_aPassword1', + 'error_type' => Exception::class, + 'error_message' => ['"%1" is not a valid email address.', 'Email'], + ], + 'empty_password' => [ + 'customer_data' => [], + 'password' => '', + 'error_type' => InputException::class, + 'error_message' => ['The password needs at least 8 characters. Create a new password and try again.'], + ], + 'invalid_password_minimum_length' => [ + 'customer_data' => [], + 'password' => 'test', + 'error_type' => InputException::class, + 'error_message' => ['The password needs at least 8 characters. Create a new password and try again.'], + ], + 'invalid_password_maximum_length' => [ + 'customer_data' => [], + 'password' => $this->getRandomNumericString(257), + 'error_type' => InputException::class, + 'error_message' => ['Please enter a password with at most 256 characters.'], + ], + 'invalid_password_without_minimum_characters_classes' => [ + 'customer_data' => [], + 'password' => 'test_password', + 'error_type' => InputException::class, + 'error_message' => [ + 'Minimum of different classes of characters in password is %1.' + . ' Classes of characters: Lower Case, Upper Case, Digits, Special Characters.', + 3, + ], + ], + 'password_same_as_email' => [ + 'customer_data' => ['email' => 'test1@test.com'], + 'password' => 'test1@test.com', + 'error_type' => LocalizedException::class, + 'error_message' => [ + 'The password can\'t be the same as the email address. Create a new password and try again.', + ], + ], + ]; + } + + /** + * Returns random numeric string with given length. + * + * @param int $length + * @return string + */ + private function getRandomNumericString(int $length): string + { + $string = ''; + for ($i = 0; $i <= $length; $i++) { + $string .= Random::getRandomNumber(0, 9); + } + + return $string; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php new file mode 100644 index 0000000000000..7820316d9f41f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\AccountManagement; + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Model\AccountManagement; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use Magento\TestFramework\Mail\Template\TransportBuilderMock; +use PHPUnit\Framework\TestCase; + +/** + * Class checks password forgot scenarios + * + * @magentoDbIsolation enabled + */ +class ForgotPasswordTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var AccountManagementInterface */ + private $accountManagement; + + /** @var TransportBuilderMock */ + private $transportBuilder; + + /** @var string */ + private $newPasswordLinkPath = "//a[contains(@href, 'customer/account/createPassword') " + . "and contains(text(), 'Set a New Password')]"; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->accountManagement = $this->objectManager->get(AccountManagementInterface::class); + $this->transportBuilder = $this->objectManager->get(TransportBuilderMock::class); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testForgotPassword(): void + { + $email = 'customer@example.com'; + $result = $this->accountManagement->initiatePasswordReset($email, AccountManagement::EMAIL_RESET); + $message = $this->transportBuilder->getSentMessage(); + $messageContent = $message->getBody()->getParts()[0]->getRawContent(); + $this->assertTrue($result); + $this->assertEquals(1, Xpath::getElementsCountForXpath($this->newPasswordLinkPath, $messageContent)); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php new file mode 100644 index 0000000000000..c6e1a9bbf8ac5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -0,0 +1,364 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Api\Data\AddressInterfaceFactory; +use Magento\Customer\Model\AddressRegistry; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Address; +use Magento\Framework\Exception\InputException; +use Magento\TestFramework\Directory\Model\GetRegionIdByName; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was created as expected or address create throws expected error. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * + * @magentoDbIsolation enabled + */ +class CreateAddressTest extends TestCase +{ + /** + * Static customer address data. + */ + private const STATIC_CUSTOMER_ADDRESS_DATA = [ + AddressInterface::TELEPHONE => 3468676, + AddressInterface::POSTCODE => 75477, + AddressInterface::COUNTRY_ID => 'US', + 'custom_region_name' => 'Alabama', + AddressInterface::CITY => 'CityM', + AddressInterface::STREET => ['Green str, 67'], + AddressInterface::LASTNAME => 'Smith', + AddressInterface::FIRSTNAME => 'John', + ]; + + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * @var AddressInterfaceFactory + */ + protected $addressFactory; + + /** + * @var CustomerRegistry + */ + protected $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + protected $addressRepository; + + /** + * @var GetRegionIdByName + */ + protected $getRegionIdByName; + + /** + * @var CustomerRepositoryInterface + */ + protected $customerRepository; + + /** + * @var AddressRegistry + */ + private $addressRegistry; + + /** + * @var Address + */ + private $addressResource; + + /** + * @var int[] + */ + private $createdAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->addressFactory = $this->objectManager->get(AddressInterfaceFactory::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->getRegionIdByName = $this->objectManager->get(GetRegionIdByName::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + $this->addressRegistry = $this->objectManager->get(AddressRegistry::class); + $this->addressResource = $this->objectManager->get(Address::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + foreach ($this->createdAddressesIds as $createdAddressesId) { + $this->addressRegistry->remove($createdAddressesId); + } + parent::tearDown(); + } + + /** + * Assert that default addresses properly created for customer. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createDefaultAddressesDataProvider + * + * @param array $addressData + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @return void + */ + public function testCreateDefaultAddress( + array $addressData, + bool $isShippingDefault, + bool $isBillingDefault + ): void { + $customer = $this->customerRepository->get('customer5@example.com'); + $this->assertNull($customer->getDefaultShipping(), 'Customer already has default shipping address'); + $this->assertNull($customer->getDefaultBilling(), 'Customer already has default billing address'); + $address = $this->createAddress( + (int)$customer->getId(), + $addressData, + $isShippingDefault, + $isBillingDefault + ); + $expectedShipping = $isShippingDefault ? $address->getId() : null; + $expectedBilling = $isBillingDefault ? $address->getId() : null; + $customer = $this->customerRepository->get('customer5@example.com'); + $this->assertEquals($expectedShipping, $customer->getDefaultShipping()); + $this->assertEquals($expectedBilling, $customer->getDefaultBilling()); + } + + /** + * Data provider for create default or not default address. + * + * @return array + */ + public function createDefaultAddressesDataProvider(): array + { + return [ + 'any_addresses_are_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, false, false], + 'shipping_address_is_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, true, false], + 'billing_address_is_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, false, true], + 'all_addresses_are_default' => [self::STATIC_CUSTOMER_ADDRESS_DATA, true, true], + ]; + } + + /** + * Assert that address created successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createAddressesDataProvider + * + * @param array $addressData + * @param array $expectedData + * @return void + */ + public function testAddressCreatedWithProperData(array $addressData, array $expectedData): void + { + if (isset($expectedData['custom_region_name'])) { + $expectedData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $expectedData['custom_region_name'], + $expectedData[AddressInterface::COUNTRY_ID] + ); + unset($expectedData['custom_region_name']); + } + $customer = $this->customerRepository->get('customer5@example.com'); + $createdAddressData = $this->createAddress((int)$customer->getId(), $addressData)->__toArray(); + foreach ($expectedData as $fieldCode => $expectedValue) { + $this->assertTrue(isset($createdAddressData[$fieldCode]), "Field $fieldCode wasn't found."); + $this->assertEquals($createdAddressData[$fieldCode], $expectedValue); + } + } + + /** + * Data provider for create address with proper data. + * + * @return array + */ + public function createAddressesDataProvider(): array + { + return [ + 'required_fields_valid_data' => [ + self::STATIC_CUSTOMER_ADDRESS_DATA, + [ + AddressInterface::TELEPHONE => 3468676, + AddressInterface::COUNTRY_ID => 'US', + AddressInterface::POSTCODE => 75477, + 'custom_region_name' => 'Alabama', + AddressInterface::FIRSTNAME => 'John', + AddressInterface::LASTNAME => 'Smith', + AddressInterface::STREET => ['Green str, 67'], + AddressInterface::CITY => 'CityM', + ], + ], + 'required_field_empty_postcode_for_uk' => [ + array_replace( + self::STATIC_CUSTOMER_ADDRESS_DATA, + [AddressInterface::POSTCODE => '', AddressInterface::COUNTRY_ID => 'GB'] + ), + [ + AddressInterface::COUNTRY_ID => 'GB', + AddressInterface::POSTCODE => null, + ], + ], + 'required_field_empty_region_id_for_ua' => [ + array_replace( + self::STATIC_CUSTOMER_ADDRESS_DATA, + [AddressInterface::REGION_ID => '', AddressInterface::COUNTRY_ID => 'UA'] + ), + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION => [ + 'region' => null, + 'region_code' => null, + 'region_id' => 0, + ], + ], + ], + 'required_field_street_as_array' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => ['', 'Green str, 67']]), + [AddressInterface::STREET => ['Green str, 67']], + ], + 'field_name_prefix' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::PREFIX => 'My prefix']), + [AddressInterface::PREFIX => 'My prefix'], + ], + 'field_middle_name_initial' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::MIDDLENAME => 'My middle name']), + [AddressInterface::MIDDLENAME => 'My middle name'], + ], + 'field_name_suffix' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::SUFFIX => 'My suffix']), + [AddressInterface::SUFFIX => 'My suffix'], + ], + 'field_company_name' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::COMPANY => 'My company']), + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::VAT_ID => 'My VAT number']), + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that proper error message has thrown if address creating with wrong data. + * + * @magentoDataFixture Magento/Customer/_files/customer_no_address.php + * + * @dataProvider createWrongAddressesDataProvider + * + * @param array $addressData + * @param \Exception $expectException + * @return void + */ + public function testExceptionThrownDuringCreateAddress(array $addressData, \Exception $expectException): void + { + $customer = $this->customerRepository->get('customer5@example.com'); + $this->expectExceptionObject($expectException); + $this->createAddress((int)$customer->getId(), $addressData); + } + + /** + * Data provider for create address with wrong data. + * + * @return array + */ + public function createWrongAddressesDataProvider(): array + { + return [ + 'required_field_empty_telephone' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::TELEPHONE => '']), + InputException::requiredField('telephone'), + ], + 'required_field_empty_postcode_for_us' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::POSTCODE => '']), + InputException::requiredField('postcode'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::REGION_ID => '']), +// InputException::requiredField('regionId'), +// ], + 'required_field_empty_firstname' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::FIRSTNAME => '']), + InputException::requiredField('firstname'), + ], + 'required_field_empty_lastname' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::LASTNAME => '']), + InputException::requiredField('lastname'), + ], + 'required_field_empty_street_as_array' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => []]), + InputException::requiredField('street'), + ], + 'required_field_empty_city' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::CITY => '']), + InputException::requiredField('city'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'field_invalid_vat_number' => [ +// array_merge(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::VAT_ID => '/>.<*']), +// null// It need to create some error but currently magento doesn't has validation for this field., +// ], + ]; + } + + /** + * Create customer address with provided address data. + * + * @param int $customerId + * @param array $addressData + * @param bool $isDefaultShipping + * @param bool $isDefaultBilling + * @return AddressInterface + */ + protected function createAddress( + int $customerId, + array $addressData, + bool $isDefaultShipping = false, + bool $isDefaultBilling = false + ): AddressInterface { + if (isset($addressData['custom_region_name'])) { + $addressData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $addressData['custom_region_name'], + $addressData[AddressInterface::COUNTRY_ID] + ); + unset($addressData['custom_region_name']); + } + + $addressData['attribute_set_id'] = $this->addressResource->getEntityType()->getDefaultAttributeSetId(); + $address = $this->addressFactory->create(['data' => $addressData]); + $address->setCustomerId($customerId); + $address->setIsDefaultShipping($isDefaultShipping); + $address->setIsDefaultBilling($isDefaultBilling); + $address = $this->addressRepository->save($address); + $this->customerRegistry->remove($customerId); + $this->addressRegistry->remove($address->getId()); + $this->createdAddressesIds[] = (int)$address->getId(); + + return $address; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php new file mode 100644 index 0000000000000..b303e8b0d1ca7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was deleted successfully. + * + * @magentoDbIsolation enabled + */ +class DeleteAddressTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var CustomerRegistry + */ + protected $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + protected $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + protected $customerRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + parent::setUp(); + } + + /** + * Assert that address deleted successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @return void + */ + public function testDeleteDefaultAddress(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $customerAddresses = $customer->getAddresses() ?? []; + foreach ($customerAddresses as $address) { + $this->addressRepository->delete($address); + } + $this->customerRegistry->remove($customer->getId()); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertNull($customer->getDefaultShipping()); + $this->assertNull($customer->getDefaultBilling()); + } + + /** + * Assert that deleting non-existent address throws exception. + * + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage No such entity with addressId = 1 + * + * @return void + */ + public function testDeleteMissingAddress(): void + { + $this->addressRepository->deleteById(1); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php new file mode 100644 index 0000000000000..902c9ae2407a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php @@ -0,0 +1,294 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\Address; + +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\AddressRegistry; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Address; +use Magento\Framework\Exception\InputException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assert that address was updated as expected or address update throws expected error. + * + * @magentoDbIsolation enabled + */ +class UpdateAddressTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var AddressRegistry + */ + protected $addressRegistry; + + /** + * @var Address + */ + protected $addressResource; + + /** + * @var CustomerRegistry + */ + protected $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + protected $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + protected $customerRepository; + + /** + * @var int[] + */ + protected $processedAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->addressRegistry = $this->objectManager->get(AddressRegistry::class); + $this->addressResource = $this->objectManager->get(Address::class); + $this->customerRegistry = $this->objectManager->get(CustomerRegistry::class); + $this->addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + foreach ($this->processedAddressesIds as $createdAddressesId) { + $this->addressRegistry->remove($createdAddressesId); + } + parent::tearDown(); + } + + /** + * Assert that default addresses properly updated for customer. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressIsDefaultDataProvider + * + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @param int|null $expectedShipping + * @param int|null $expectedBilling + * @return void + */ + public function testUpdateAddressIsDefault( + bool $isShippingDefault, + bool $isBillingDefault, + ?int $expectedShipping, + ?int $expectedBilling + ): void { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + $address->setIsDefaultShipping($isShippingDefault); + $address->setIsDefaultBilling($isBillingDefault); + $this->addressRepository->save($address); + $this->customerRegistry->remove(1); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals($customer->getDefaultShipping(), $expectedShipping); + $this->assertEquals($customer->getDefaultBilling(), $expectedBilling); + } + + /** + * Data provider for update address as default billing or default shipping. + * + * @return array + */ + public function updateAddressIsDefaultDataProvider(): array + { + return [ + 'update_shipping_address_default' => [true, false, 1, null], + 'update_billing_address_default' => [false, true, null, 1], + ]; + } + + /** + * Assert that address updated successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressesDataProvider + * + * @param array $updateData + * @param array $expectedData + * @return void + */ + public function testUpdateAddress(array $updateData, array $expectedData): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $updatedAddressData = $this->addressRepository->save($address)->__toArray(); + foreach ($expectedData as $getFieldName => $getValue) { + $this->assertTrue(isset($updatedAddressData[$getFieldName]), "Field $getFieldName wasn't found."); + $this->assertEquals($getValue, $updatedAddressData[$getFieldName]); + } + } + + /** + * Data provider for update address with proper data. + * + * @return array + */ + public function updateAddressesDataProvider(): array + { + return [ + 'required_field_telephone' => [ + [AddressInterface::TELEPHONE => 251512979595], + [AddressInterface::TELEPHONE => 251512979595], + ], + 'required_field_postcode' => [ + [AddressInterface::POSTCODE => 55425], + [AddressInterface::POSTCODE => 55425], + ], + 'required_field_empty_postcode_for_uk' => [ + [AddressInterface::COUNTRY_ID => 'GB', AddressInterface::POSTCODE => ''], + [AddressInterface::COUNTRY_ID => 'GB', AddressInterface::POSTCODE => null], + ], + 'required_field_empty_region_id_for_ua' => [ + [AddressInterface::COUNTRY_ID => 'UA', AddressInterface::REGION_ID => ''], + [ + AddressInterface::COUNTRY_ID => 'UA', + AddressInterface::REGION_ID => 0, + ], + ], + 'required_field_firstname' => [ + [AddressInterface::FIRSTNAME => 'Test firstname'], + [AddressInterface::FIRSTNAME => 'Test firstname'], + ], + 'required_field_lastname' => [ + [AddressInterface::LASTNAME => 'Test lastname'], + [AddressInterface::LASTNAME => 'Test lastname'], + ], + 'required_field_street_as_array' => [ + [AddressInterface::STREET => ['', 'Test str, 55']], + [AddressInterface::STREET => ['Test str, 55']], + ], + 'required_field_city' => [ + [AddressInterface::CITY => 'Test city'], + [AddressInterface::CITY => 'Test city'], + ], + 'field_name_prefix' => [ + [AddressInterface::PREFIX => 'My prefix'], + [AddressInterface::PREFIX => 'My prefix'], + ], + 'field_middle_name_initial' => [ + [AddressInterface::MIDDLENAME => 'My middle name'], + [AddressInterface::MIDDLENAME => 'My middle name'], + ], + 'field_name_suffix' => [ + [AddressInterface::SUFFIX => 'My suffix'], + [AddressInterface::SUFFIX => 'My suffix'], + ], + 'field_company_name' => [ + [AddressInterface::COMPANY => 'My company'], + [AddressInterface::COMPANY => 'My company'], + ], + 'field_vat_number' => [ + [AddressInterface::VAT_ID => 'My VAT number'], + [AddressInterface::VAT_ID => 'My VAT number'], + ], + ]; + } + + /** + * Assert that error message has thrown during process address update. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateWrongAddressesDataProvider + * + * @param array $updateData + * @param \Exception $expectException + * @return void + */ + public function testExceptionThrownDuringUpdateAddress(array $updateData, \Exception $expectException): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $this->expectExceptionObject($expectException); + $this->addressRepository->save($address); + } + + /** + * Data provider for update address with proper data or with error. + * + * @return array + */ + public function updateWrongAddressesDataProvider(): array + { + return [ + 'required_field_empty_telephone' => [ + [AddressInterface::TELEPHONE => ''], + InputException::requiredField('telephone'), + ], + 'required_field_empty_postcode_for_us' => [ + [AddressInterface::POSTCODE => ''], + InputException::requiredField('postcode'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'required_field_empty_region_id_for_us' => [ +// [AddressInterface::REGION_ID => ''], +// InputException::requiredField('regionId'), +// ], + 'required_field_empty_firstname' => [ + [AddressInterface::FIRSTNAME => ''], + InputException::requiredField('firstname'), + ], + 'required_field_empty_lastname' => [ + [AddressInterface::LASTNAME => ''], + InputException::requiredField('lastname'), + ], + 'required_field_empty_street_as_array' => [ + [AddressInterface::STREET => []], + InputException::requiredField('street'), + ], + 'required_field_empty_city' => [ + [AddressInterface::CITY => ''], + InputException::requiredField('city'), + ], +// TODO: Uncomment this variation after fix issue https://jira.corp.magento.com/browse/MC-31031 +// 'field_invalid_vat_number' => [ +// [AddressInterface::VAT_ID => '/>.<*'], +// null// It need to create some error but currently magento doesn't has validation for this field., +// ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php new file mode 100644 index 0000000000000..866fd2c97207e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model; + +use Magento\Customer\Model\Metadata\AddressMetadata; +use Magento\Eav\Model\Config; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +class CustomerAddressAttributeTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Config + */ + private $config; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->config = $objectManager->get(Config::class); + $this->storeManager = $objectManager->get(StoreManagerInterface::class); + } + + /** + * Tests cached scope_is_required attribute value for a certain website + * + * @return void + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + */ + public function testGetScopeIsRequiredAttributeValueFromCache(): void + { + $attributeCode = 'telephone'; + $entityType = AddressMetadata::ENTITY_TYPE_ADDRESS; + $attribute = $this->config->getAttribute($entityType, $attributeCode); + $currentStore = $this->storeManager->getStore(); + $secondWebsite = $this->storeManager->getWebsite('test'); + $attribute->setWebsite($secondWebsite->getId()); + $attribute->setData('scope_is_required', '0'); + $attribute->save(); + $this->config->getAttribute($entityType, $attributeCode); + $this->storeManager->setCurrentStore('fixture_second_store'); + try { + $this->config->getEntityAttributes($attribute->getEntityTypeId(), $attribute); + $scopeAttribute = $this->config->getAttribute($entityType, $attributeCode); + $this->assertEquals(0, $scopeAttribute->getIsRequired()); + } finally { + $this->storeManager->setCurrentStore($currentStore); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Metadata/FormTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Metadata/FormTest.php index 355167d809ba3..a510c6c4e6616 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Metadata/FormTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Metadata/FormTest.php @@ -5,9 +5,11 @@ */ namespace Magento\Customer\Model\Metadata; +use Magento\Framework\App\RequestInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; -class FormTest extends \PHPUnit\Framework\TestCase +class FormTest extends TestCase { /** * @var Form @@ -17,7 +19,7 @@ class FormTest extends \PHPUnit\Framework\TestCase /** @var array */ protected $_attributes; - /** @var \Magento\Framework\App\RequestInterface */ + /** @var RequestInterface */ protected $_request; /** @var array */ @@ -31,7 +33,7 @@ public function setUp() $objectManager = Bootstrap::getObjectManager(); /** @var FormFactory $formFactory */ - $formFactory = $objectManager->create(\Magento\Customer\Model\Metadata\FormFactory::class); + $formFactory = $objectManager->create(FormFactory::class); $this->_form = $formFactory->create('customer_address', 'customer_address_edit'); $this->_attributes = [ @@ -70,7 +72,7 @@ public function setUp() 'region_id' => 12, 'region' => 'California', ]; - $this->_request = $objectManager->get(\Magento\Framework\App\RequestInterface::class); + $this->_request = $objectManager->get(RequestInterface::class); $this->_request->setParams($requestData); $this->_expected = array_merge($this->_attributes, $requestData); @@ -105,10 +107,10 @@ public function testGetAttributes() 'suffix', 'company', 'street', - 'city', 'country_id', 'region', 'region_id', + 'city', 'postcode', 'telephone', 'fax', diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/CreateAddressTest.php new file mode 100644 index 0000000000000..a866910332b0c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/CreateAddressTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\ResourceModel\CustomerRepository; + +use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Model\Address\CreateAddressTest as CreateAddressViaAddressRepositoryTest; +use Magento\Framework\Api\DataObjectHelper; + +/** + * Test cases related to create customer address using customer repository. + * + * @magentoDbIsolation enabled + */ +class CreateAddressTest extends CreateAddressViaAddressRepositoryTest +{ + /** + * @var DataObjectHelper + */ + private $dataObjectHelper; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->dataObjectHelper = $this->objectManager->get(DataObjectHelper::class); + } + + /** + * Create customer address with provided address data. + * + * @param int $customerId + * @param array $addressData + * @param bool $isDefaultShipping + * @param bool $isDefaultBilling + * @return AddressInterface + */ + protected function createAddress( + int $customerId, + array $addressData, + bool $isDefaultShipping = false, + bool $isDefaultBilling = false + ): AddressInterface { + if (isset($addressData['custom_region_name'])) { + $addressData[AddressInterface::REGION_ID] = $this->getRegionIdByName->execute( + $addressData['custom_region_name'], + $addressData[AddressInterface::COUNTRY_ID] + ); + unset($addressData['custom_region_name']); + } + $address = $this->addressFactory->create(); + $this->dataObjectHelper->populateWithArray($address, $addressData, AddressInterface::class); + $address->setIsDefaultShipping($isDefaultShipping); + $address->setIsDefaultBilling($isDefaultBilling); + $customer = $this->customerRepository->getById($customerId); + $customer->setAddresses([$address]); + $this->customerRepository->save($customer); + $addressId = (int)$address->getId(); + $this->customerRegistry->remove($customerId); + + return $this->addressRepository->getById($addressId); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/DeleteAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/DeleteAddressTest.php new file mode 100644 index 0000000000000..dd3adebc92cc2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/DeleteAddressTest.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\ResourceModel\CustomerRepository; + +use Magento\Customer\Model\Address\DeleteAddressTest as DeleteAddressViaAddressRepositoryTest; +use Magento\Framework\Exception\NoSuchEntityException; + +/** + * Test cases related to delete customer address using customer repository. + * + * @magentoDbIsolation enabled + */ +class DeleteAddressTest extends DeleteAddressViaAddressRepositoryTest +{ + /** + * Assert that address deleted successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @return void + */ + public function testDeleteDefaultAddress(): void + { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $customer->setAddresses([]); + $this->customerRepository->save($customer); + $this->customerRegistry->remove($customer->getId()); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertNull($customer->getDefaultShipping()); + $this->assertNull($customer->getDefaultBilling()); + $this->expectExceptionObject(new NoSuchEntityException(__('No such entity with addressId = 1'))); + $this->addressRepository->getById(1); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/UpdateAddressTest.php new file mode 100644 index 0000000000000..789c61bdbaf5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/UpdateAddressTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Model\ResourceModel\CustomerRepository; + +use Magento\Customer\Model\Address\UpdateAddressTest as UpdateAddressViaAddressRepositoryTest; + +/** + * Test cases related to update customer address using customer repository. + * + * @magentoDbIsolation enabled + */ +class UpdateAddressTest extends UpdateAddressViaAddressRepositoryTest +{ + /** + * Assert that default addresses properly updated for customer. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressIsDefaultDataProvider + * + * @param bool $isShippingDefault + * @param bool $isBillingDefault + * @param int|null $expectedShipping + * @param int|null $expectedBilling + * @return void + */ + public function testUpdateAddressIsDefault( + bool $isShippingDefault, + bool $isBillingDefault, + ?int $expectedShipping, + ?int $expectedBilling + ): void { + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals(1, $customer->getDefaultShipping()); + $this->assertEquals(1, $customer->getDefaultBilling()); + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + $address->setIsDefaultShipping($isShippingDefault); + $address->setIsDefaultBilling($isBillingDefault); + $customer->setAddresses([$address]); + $this->customerRepository->save($customer); + $this->customerRegistry->remove(1); + $customer = $this->customerRepository->get('customer@example.com'); + $this->assertEquals($customer->getDefaultShipping(), $expectedShipping); + $this->assertEquals($customer->getDefaultBilling(), $expectedBilling); + } + + /** + * Assert that address updated successfully. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateAddressesDataProvider + * + * @param array $updateData + * @param array $expectedData + * @return void + */ + public function testUpdateAddress(array $updateData, array $expectedData): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $customer = $this->customerRepository->get('customer@example.com'); + $customer->setAddresses([$address]); + $this->customerRepository->save($customer); + $updatedAddressData = $this->addressRepository->getById((int)$address->getId())->__toArray(); + foreach ($expectedData as $getFieldName => $getValue) { + $this->assertTrue(isset($updatedAddressData[$getFieldName]), "Field $getFieldName wasn't found."); + $this->assertEquals($getValue, $updatedAddressData[$getFieldName]); + } + } + + /** + * Assert that error message has thrown during process address update. + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * + * @dataProvider updateWrongAddressesDataProvider + * + * @param array $updateData + * @param \Exception $expectException + * @return void + */ + public function testExceptionThrownDuringUpdateAddress(array $updateData, \Exception $expectException): void + { + $this->processedAddressesIds[] = 1; + $address = $this->addressRepository->getById(1); + $customer = $this->customerRepository->get('customer@example.com'); + foreach ($updateData as $setFieldName => $setValue) { + $address->setData($setFieldName, $setValue); + } + $customer->setAddresses([$address]); + $this->expectExceptionObject($expectException); + $this->customerRepository->save($customer); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php new file mode 100644 index 0000000000000..9909856322e13 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +/** @var CustomerRegistry $customerRegistry */ +$customerRegistry = $objectManager->get(CustomerRegistry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +try { + $customerRegistry->remove(5); + $customerRepository->deleteById(5); +} catch (NoSuchEntityException $e) { + //Customer already deleted. +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer.php b/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer.php new file mode 100644 index 0000000000000..2e298a7e508a3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\CustomerMetadataInterface; +use Magento\Customer\Model\Data\CustomerFactory; +use Magento\Customer\Model\GroupManagement; +use Magento\Eav\Model\AttributeRepository; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var AccountManagementInterface $accountManagement */ +$accountManagement = $objectManager->get(AccountManagementInterface::class); +$customerFactory = $objectManager->get(CustomerFactory::class); +$customerFactory->create(); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$website = $storeManager->getWebsite('base'); +/** @var GroupManagement $groupManagement */ +$groupManagement = $objectManager->get(GroupManagement::class); +$defaultStoreId = $website->getDefaultStore()->getId(); +/** @var AttributeRepository $attributeRepository */ +$attributeRepository = $objectManager->get(AttributeRepository::class); +$gender = $attributeRepository->get(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'gender') + ->getSource()->getOptionId('Male'); +$customer = $customerFactory->create(); +$customer->setWebsiteId($website->getId()) + ->setEmail('new_customer@example.com') + ->setGroupId($groupManagement->getDefaultGroup($defaultStoreId)->getId()) + ->setStoreId($defaultStoreId) + ->setPrefix('Mr.') + ->setFirstname('John') + ->setMiddlename('A') + ->setLastname('Smith') + ->setSuffix('Esq.') + ->setDefaultBilling(1) + ->setDefaultShipping(1) + ->setGender($gender); +$accountManagement->createAccount($customer, 'Qwert12345'); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer_rollback.php new file mode 100644 index 0000000000000..48da309f6878f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/new_customer_rollback.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$websiteId = $websiteRepository->get('base')->getId(); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $customer = $customerRepository->get('new_customer@example.com', $websiteId); + $customerRepository->delete($customer); +} catch (NoSuchEntityException $e) { + //customer already deleted +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer.php b/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer.php new file mode 100644 index 0000000000000..e27010dc042ca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\CustomerMetadataInterface; +use Magento\Customer\Model\Data\CustomerFactory; +use Magento\Eav\Model\AttributeRepository; +use Magento\Framework\Math\Random; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var AccountManagementInterface $accountManagment */ +$accountManagment = $objectManager->get(AccountManagementInterface::class); +/** @var CustomerFactory $customerFactory */ +$customerFactory = $objectManager->get(CustomerFactory::class); +/** @var Random $random */ +$random = $objectManager->get(Random::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$customer = $customerFactory->create(); +$website = $websiteRepository->get('base'); +$defaultStoreId = $website->getDefaultStore()->getId(); +/** @var AttributeRepository $attributeRepository */ +$attributeRepository = $objectManager->get(AttributeRepository::class); +$gender = $attributeRepository->get(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER, 'gender') + ->getSource()->getOptionId('Male'); + +$customer->setWebsiteId($website->getId()) + ->setEmail('unconfirmedcustomer@example.com') + ->setGroupId(1) + ->setStoreId($defaultStoreId) + ->setPrefix('Mr.') + ->setFirstname('John') + ->setMiddlename('A') + ->setLastname('Smith') + ->setSuffix('Esq.') + ->setDefaultBilling(1) + ->setDefaultShipping(1) + ->setConfirmation($random->getUniqueHash()) + ->setGender($gender); + +$accountManagment->createAccount($customer, 'Qwert12345'); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer_rollback.php new file mode 100644 index 0000000000000..cbe30d4d24fcb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer_rollback.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$websiteId = $websiteRepository->get('base')->getId(); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $customer = $customerRepository->get('unconfirmedcustomer@example.com', $websiteId); + $customerRepository->delete($customer); +} catch (NoSuchEntityException $e) { + //customer already deleted +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock index 4fb998ab77b34..d9da3edf3d209 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock +++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testFromCreateProject/composer.lock @@ -2460,10 +2460,6 @@ "app/etc/registration_globlist.php", "app/etc/registration_globlist.php" ], - [ - "app/functions.php", - "app/functions.php" - ], [ "auth.json.sample", "auth.json.sample" diff --git a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock index 36a98e6cd9596..d755bfa0479e6 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock +++ b/dev/tests/integration/testsuite/Magento/Framework/Composer/_files/testSkeleton/composer.lock @@ -2460,10 +2460,6 @@ "app/etc/registration_globlist.php", "app/etc/registration_globlist.php" ], - [ - "app/functions.php", - "app/functions.php" - ], [ "auth.json.sample", "auth.json.sample" diff --git a/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Driver/FileTest.php b/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Driver/FileTest.php index 5f53e62165502..c8719ea7e0a0a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Driver/FileTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Driver/FileTest.php @@ -5,11 +5,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\Filesystem\Driver; use Magento\Framework\Exception\FileSystemException; +use PHPUnit\Framework\TestCase; -class FileTest extends \PHPUnit\Framework\TestCase +/** + * Verify File class + */ +class FileTest extends TestCase { /** * @var File @@ -50,16 +56,20 @@ public function setUp() /** * @inheritdoc + * + * @return void */ - protected function tearDown() + protected function tearDown(): void { $this->removeGeneratedDirectory(); } /** * Tests directory recursive read. + * + * @return void */ - public function testReadDirectoryRecursively() + public function testReadDirectoryRecursively(): void { $paths = [ 'foo/bar', @@ -77,9 +87,10 @@ public function testReadDirectoryRecursively() /** * Tests directory reading exception. * + * @return void * @expectedException \Magento\Framework\Exception\FileSystemException */ - public function testReadDirectoryRecursivelyFailure() + public function testReadDirectoryRecursivelyFailure(): void { $this->driver->readDirectoryRecursively($this->getTestPath('not-existing-directory')); } @@ -88,8 +99,9 @@ public function testReadDirectoryRecursivelyFailure() * Tests of directory creating. * * @throws FileSystemException + * @return void */ - public function testCreateDirectory() + public function testCreateDirectory(): void { $generatedPath = $this->getTestPath('generated/roo/bar/baz/foo'); $generatedPathBase = $this->getTestPath('generated'); @@ -123,6 +135,18 @@ public function testSymlinks(): void self::assertTrue($this->driver->deleteDirectory($linkName)); } + /** + * Verify file put content without content. + * + * @return void + * @throws FileSystemException + */ + public function testFilePutWithoutContents(): void + { + $path = $this->absolutePath . 'foo/file_three.txt'; + $this->assertEquals(0, $this->driver->filePutContents($path, '')); + } + /** * Remove generated directories. * diff --git a/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Io/FileTest.php b/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Io/FileTest.php new file mode 100644 index 0000000000000..39503ec87f8e6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Filesystem/Io/FileTest.php @@ -0,0 +1,92 @@ +<?php +/** + * Test for \Magento\Framework\Filesystem\Io\File + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\Filesystem\Io; + +use Magento\Framework\Exception\FileSystemException; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Verify filesystem client + */ +class FileTest extends TestCase +{ + + /** + * @var File + */ + private $io; + + /** + * @var String + */ + private $absolutePath; + + /** + * @var String + */ + private $generatedPath; + + /** + * @inheritDoc + */ + public function setUp() + { + $this->io = new File(); + $this->absolutePath = Bootstrap::getInstance()->getAppTempDir(); + $this->generatedPath = $this->getTestPath('/rollback_test_'); + $this->io->mkdir($this->generatedPath); + } + + /** + * @inheritdoc + * + * @return void + */ + protected function tearDown(): void + { + $this->removeGeneratedDirectory(); + } + + /** + * Verify file put without content. + * + * @return void + */ + public function testWrite(): void + { + $path = $this->generatedPath . '/file_three.txt'; + $this->assertEquals(0, $this->io->write($path, '', 0444)); + $this->assertEquals(false, is_writable($path)); + } + + /** + * Returns relative path for the test. + * + * @param $relativePath + * @return string + */ + protected function getTestPath($relativePath): string + { + return $this->absolutePath . $relativePath . time(); + } + + /** + * Remove generated directories. + * + * @return void + */ + private function removeGeneratedDirectory(): void + { + if (is_dir($this->generatedPath)) { + $this->io->rmdir($this->generatedPath, true); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/Session/SaveHandlerTest.php b/dev/tests/integration/testsuite/Magento/Framework/Session/SaveHandlerTest.php index c420f6fa9dd75..dd493a499e855 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Session/SaveHandlerTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Session/SaveHandlerTest.php @@ -3,18 +3,25 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Session; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Exception\SessionException; use Magento\Framework\Phrase; use Magento\Framework\Session\Config\ConfigInterface; -use Magento\Framework\App\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +/** + * Tests \Magento\Framework\Session\SaveHandler functionality. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class SaveHandlerTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ private $objectManager; @@ -28,15 +35,21 @@ class SaveHandlerTest extends \PHPUnit\Framework\TestCase */ private $saveHandlerFactoryMock; + /** + * @inheritdoc + */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); $this->deploymentConfigMock = $this->createMock(DeploymentConfig::class); $this->objectManager->addSharedInstance($this->deploymentConfigMock, DeploymentConfig::class); $this->saveHandlerFactoryMock = $this->createMock(SaveHandlerFactory::class); $this->objectManager->addSharedInstance($this->saveHandlerFactoryMock, SaveHandlerFactory::class); } + /** + * @inheritdoc + */ protected function tearDown() { $this->objectManager->removeSharedInstance(DeploymentConfig::class); @@ -44,99 +57,74 @@ protected function tearDown() } /** - * Tests that the session handler is correctly set when object is created. - * - * @dataProvider saveHandlerProvider - * @param string $deploymentConfigHandler + * @return void */ - public function testConstructor($deploymentConfigHandler) + public function testRedisSaveHandler(): void { - $expected = $this->getExpectedSaveHandler($deploymentConfigHandler, ini_get('session.save_handler')); - $this->deploymentConfigMock->method('get') - ->willReturnCallback(function ($configPath) use ($deploymentConfigHandler) { - switch ($configPath) { - case Config::PARAM_SESSION_SAVE_METHOD: - return $deploymentConfigHandler; - case Config::PARAM_SESSION_CACHE_LIMITER: - return 'private_no_expire'; - case Config::PARAM_SESSION_SAVE_PATH: - return 'explicit_save_path'; - default: - return null; - } - }); - - $this->saveHandlerFactoryMock->expects($this->once()) - ->method('create') - ->with($expected); - $sessionConfig = $this->objectManager->create(ConfigInterface::class); - $this->objectManager->create(SaveHandler::class, ['sessionConfig' => $sessionConfig]); + ->willReturnMap( + [ + [Config::PARAM_SESSION_SAVE_METHOD, null, 'redis'], + [Config::PARAM_SESSION_SAVE_PATH, null, 'explicit_save_path'], + ] + ); - // Test expectation - $this->assertEquals( - $expected, - $sessionConfig->getOption('session.save_handler') - ); - } + $redisHandlerMock = $this->getMockBuilder(SaveHandler\Redis::class) + ->disableOriginalConstructor() + ->getMock(); + $redisHandlerMock->method('open') + ->with('explicit_save_path', 'test_session_id') + ->willReturn(true); - public function saveHandlerProvider() - { - return [ - ['db'], - ['redis'], - ['files'], - [false], - ]; + $this->saveHandlerFactoryMock->expects($this->exactly(1)) + ->method('create') + ->with('redis') + ->willReturn($redisHandlerMock); + + $sessionConfig = $this->objectManager->create(ConfigInterface::class); + /** @var SaveHandler $saveHandler */ + $saveHandler = $this->objectManager->create(SaveHandler::class, ['sessionConfig' => $sessionConfig]); + $result = $saveHandler->open('explicit_save_path', 'test_session_id'); + $this->assertTrue($result); } /** - * Retrieve expected session.save_handler - * - * @param string $deploymentConfigHandler - * @param string $iniHandler - * @return string + * @return void */ - private function getExpectedSaveHandler($deploymentConfigHandler, $iniHandler) - { - if ($deploymentConfigHandler) { - return $deploymentConfigHandler; - } elseif ($iniHandler) { - return $iniHandler; - } else { - return SaveHandlerInterface::DEFAULT_HANDLER; - } - } - - public function testConstructorWithException() + public function testRedisSaveHandlerFallbackToDefaultOnSessionException(): void { $this->deploymentConfigMock->method('get') - ->willReturnCallback(function ($configPath) { - switch ($configPath) { - case Config::PARAM_SESSION_SAVE_METHOD: - return 'db'; - case Config::PARAM_SESSION_CACHE_LIMITER: - return 'private_no_expire'; - case Config::PARAM_SESSION_SAVE_PATH: - return 'explicit_save_path'; - default: - return null; - } - }); + ->willReturnMap( + [ + [Config::PARAM_SESSION_SAVE_METHOD, null, 'redis'], + [Config::PARAM_SESSION_SAVE_PATH, null, 'explicit_save_path'], + ] + ); + + $redisHandlerMock = $this->getMockBuilder(SaveHandler\Redis::class) + ->disableOriginalConstructor() + ->getMock(); + $redisHandlerMock->method('open') + ->with('explicit_save_path', 'test_session_id') + ->willThrowException(new SessionException(new Phrase('Session Exception'))); + + $defaultHandlerMock = $this->getMockBuilder(SaveHandler\Native::class) + ->disableOriginalConstructor() + ->getMock(); + $defaultHandlerMock->expects($this->once())->method('open')->with('explicit_save_path', 'test_session_id'); $this->saveHandlerFactoryMock->expects($this->at(0)) ->method('create') - ->willThrowException(new SessionException(new Phrase('Session Exception'))); + ->with('redis') + ->willReturn($redisHandlerMock); $this->saveHandlerFactoryMock->expects($this->at(1)) ->method('create') - ->with(SaveHandlerInterface::DEFAULT_HANDLER); - $sessionConfig = $this->objectManager->create(ConfigInterface::class); - $this->objectManager->create(SaveHandler::class, ['sessionConfig' => $sessionConfig]); + ->with(SaveHandlerInterface::DEFAULT_HANDLER) + ->willReturn($defaultHandlerMock); - // Test expectation - $this->assertEquals( - 'db', - $sessionConfig->getOption('session.save_handler') - ); + $sessionConfig = $this->objectManager->create(ConfigInterface::class); + /** @var SaveHandler $saveHandler */ + $saveHandler = $this->objectManager->create(SaveHandler::class, ['sessionConfig' => $sessionConfig]); + $saveHandler->open('explicit_save_path', 'test_session_id'); } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutTest.php index 66e8eb3e453f9..a156b8f6d23ec 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutTest.php @@ -274,7 +274,7 @@ public function testAddContainerInvalidHtmlTag() { $msg = 'Html tag "span" is forbidden for usage in containers. ' . 'Consider to use one of the allowed: aside, dd, div, dl, fieldset, main, nav, ' . - 'header, footer, ol, p, section, table, tfoot, ul.'; + 'header, footer, ol, p, section, table, tfoot, ul, article.'; $this->expectException(\Magento\Framework\Exception\LocalizedException::class); $this->expectExceptionMessage($msg); $this->_layout->addContainer('container', 'Container', ['htmlTag' => 'span']); diff --git a/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php b/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php new file mode 100644 index 0000000000000..8856356227ed9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GroupedProduct\Block\Order\Email\Items\CreditMemo; + +use Magento\Sales\Block\Order\Email\Items\DefaultItems; +use Magento\Sales\Model\Order\Creditmemo; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Verify grouped product block will output correct data. + * + * @magentoAppArea frontend + */ +class GroupedTest extends TestCase +{ + /** + * Test subject. + * + * @var Grouped + */ + private $block; + + /** + * @var CreditMemo + */ + private $creditMemo; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->block = Bootstrap::getObjectManager()->get(Grouped::class); + $this->creditMemo = Bootstrap::getObjectManager()->get(CreditMemo::class); + } + + /** + * Verify, grouped block will output correct product sku and name. + * + * @magentoDataFixture Magento/Sales/_files/creditmemo_with_grouped_product.php + */ + public function testToHtml() + { + $creditMemo = $this->creditMemo->load('100000002', 'increment_id'); + $creditMemoItem = $creditMemo->getItemsCollection()->getFirstItem(); + $priceBlock = Bootstrap::getObjectManager()->create(DefaultItems::class); + $this->block->setTemplate('Magento_Sales::email/items/creditmemo/default.phtml'); + $this->block->setItem($creditMemoItem); + $this->block->getLayout()->setBlock('item_price', $priceBlock); + $output = $this->block->toHtml(); + self::assertContains('SKU: simple_11', $output); + self::assertContains('"product-name">Simple 11', $output); + } +} diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/AbstractFiltersTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/AbstractFiltersTest.php index cf39757cb8264..fc0c23b346fe2 100644 --- a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/AbstractFiltersTest.php +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/AbstractFiltersTest.php @@ -140,7 +140,7 @@ protected function getSearchFiltersAndAssert( $this->updateAttribute($attributeData); $this->updateProducts($products, $this->getAttributeCode()); $this->clearInstanceAndReindexSearch(); - $this->navigationBlock->getRequest()->setParams(['q' => 'Simple Product']); + $this->navigationBlock->getRequest()->setParams(['q' => $this->getSearchString()]); $this->navigationBlock->setLayout($this->layout); $filter = $this->getFilterByCode($this->navigationBlock->getFilters(), $this->getAttributeCode()); @@ -293,4 +293,14 @@ protected function createNavigationBlockInstance(): void $this->navigationBlock = $this->objectManager->create(CategoryNavigationBlock::class); } } + + /** + * Returns search query for filters on search page. + * + * @return string + */ + protected function getSearchString(): string + { + return 'Simple Product'; + } } diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/MultiselectFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/MultiselectFilterTest.php new file mode 100644 index 0000000000000..518a0a19f857f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/MultiselectFilterTest.php @@ -0,0 +1,109 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\LayeredNavigation\Block\Navigation\Category\Bundle; + +use Magento\Catalog\Model\Layer\Resolver; +use Magento\Framework\Module\Manager; +use Magento\LayeredNavigation\Block\Navigation\AbstractFiltersTest; +use Magento\Catalog\Model\Layer\Filter\AbstractFilter; + +/** + * Provides tests for custom multiselect filter in navigation block on category page with bundle products. + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation disabled + */ +class MultiselectFilterTest extends AbstractFiltersTest +{ + /** + * @var Manager + */ + private $moduleManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->moduleManager = $this->objectManager->get(Manager::class); + //This check is needed because LayeredNavigation independent of Magento_Bundle + if (!$this->moduleManager->isEnabled('Magento_Bundle')) { + $this->markTestSkipped('Magento_Bundle module disabled.'); + } + } + + /** + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute.php + * @magentoDataFixture Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php + * @dataProvider getFiltersWithCustomAttributeDataProvider + * @param array $products + * @param array $attributeData + * @param array $expectation + * @return void + */ + public function testGetFiltersWithCustomAttribute(array $products, array $attributeData, array $expectation): void + { + $this->getCategoryFiltersAndAssert($products, $attributeData, $expectation, 'Category 1'); + } + + /** + * @return array + */ + public function getFiltersWithCustomAttributeDataProvider(): array + { + return [ + 'not_used_in_navigation' => [ + 'products_data' => [], + 'attribute_data' => ['is_filterable' => 0], + 'expectation' => [], + ], + 'used_in_navigation_with_results' => [ + 'products_data' => [ + 'bundle-product' => 'Option 1', + 'bundle-product-dropdown-options' => 'Option 2', + ], + 'attribute_data' => ['is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS], + 'expectation' => [ + ['label' => 'Option 1', 'count' => 1], + ['label' => 'Option 2', 'count' => 1], + ], + ], + 'used_in_navigation_without_results' => [ + 'products_data' => [ + 'bundle-product' => 'Option 1', + 'bundle-product-dropdown-options' => 'Option 2', + ], + 'attribute_data' => ['is_filterable' => 2], + 'expectation' => [ + ['label' => 'Option 1', 'count' => 1], + ['label' => 'Option 2', 'count' => 1], + ['label' => 'Option 3', 'count' => 0], + ['label' => 'Option 4 "!@#$%^&*', 'count' => 0], + ], + ], + ]; + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_CATEGORY; + } + + /** + * @inheritdoc + */ + protected function getAttributeCode(): string + { + return 'multiselect_attribute'; + } +} diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/PriceFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/PriceFilterTest.php new file mode 100644 index 0000000000000..3817c5efc86fc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/PriceFilterTest.php @@ -0,0 +1,96 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\LayeredNavigation\Block\Navigation\Category\Bundle; + +use Magento\Catalog\Model\Layer\Resolver; +use Magento\Framework\Module\Manager; +use Magento\LayeredNavigation\Block\Navigation\AbstractFiltersTest; +use Magento\Catalog\Model\Layer\Filter\AbstractFilter; +use Magento\Catalog\Model\Layer\Filter\Item; + +/** + * Provides price filter tests for bundle products in navigation block on category page. + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation disabled + */ +class PriceFilterTest extends AbstractFiltersTest +{ + /** + * @var Manager + */ + private $moduleManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->moduleManager = $this->objectManager->get(Manager::class); + //This check is needed because LayeredNavigation independent of Magento_Bundle + if (!$this->moduleManager->isEnabled('Magento_Bundle')) { + $this->markTestSkipped('Magento_Bundle module disabled.'); + } + } + + /** + * @magentoDataFixture Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php + * @magentoConfigFixture current_store catalog/layered_navigation/price_range_calculation manual + * @magentoConfigFixture current_store catalog/layered_navigation/price_range_step 10 + * @return void + */ + public function testGetFilters(): void + { + $this->getCategoryFiltersAndAssert( + ['bundle-product' => 20.00], + ['is_filterable' => '1'], + [ + ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], + ['label' => '$20.00 and above', 'value' => '20-', 'count' => 1], + ], + 'Category 1' + ); + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_CATEGORY; + } + + /** + * @inheritdoc + */ + protected function getAttributeCode(): string + { + return 'price'; + } + + /** + * @inheritdoc + */ + protected function prepareFilterItems(AbstractFilter $filter): array + { + $items = []; + /** @var Item $item */ + foreach ($filter->getItems() as $item) { + $item = [ + 'label' => strip_tags(__($item->getData('label'))->render()), + 'value' => $item->getData('value'), + 'count' => $item->getData('count'), + ]; + $items[] = $item; + } + + return $items; + } +} diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/SelectFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/SelectFilterTest.php new file mode 100644 index 0000000000000..7b3be2afbdbdb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Category/Bundle/SelectFilterTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\LayeredNavigation\Block\Navigation\Category\Bundle; + +use Magento\Catalog\Model\Layer\Resolver; +use Magento\Framework\Module\Manager; +use Magento\LayeredNavigation\Block\Navigation\AbstractFiltersTest; +use Magento\Catalog\Model\Layer\Filter\AbstractFilter; + +/** + * Provides tests for custom select filter for bundle products in navigation block on category page. + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation disabled + */ +class SelectFilterTest extends AbstractFiltersTest +{ + /** + * @var Manager + */ + private $moduleManager; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->moduleManager = $this->objectManager->get(Manager::class); + //This check is needed because LayeredNavigation independent of Magento_Bundle + if (!$this->moduleManager->isEnabled('Magento_Bundle')) { + $this->markTestSkipped('Magento_Bundle module disabled.'); + } + } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_dropdown_attribute.php + * @magentoDataFixture Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php + * @dataProvider getFiltersWithCustomAttributeDataProvider + * @param array $products + * @param array $attributeData + * @param array $expectation + * @return void + */ + public function testGetFiltersWithCustomAttribute(array $products, array $attributeData, array $expectation): void + { + $this->getCategoryFiltersAndAssert($products, $attributeData, $expectation, 'Category 1'); + } + + /** + * @return array + */ + public function getFiltersWithCustomAttributeDataProvider(): array + { + return [ + 'not_used_in_navigation' => [ + 'products_data' => [], + 'attribute_data' => ['is_filterable' => 0], + 'expectation' => [], + ], + 'used_in_navigation_with_results' => [ + 'products_data' => [ + 'bundle-product' => 'Option 1', + 'bundle-product-dropdown-options' => 'Option 2', + ], + 'attribute_data' => ['is_filterable' => AbstractFilter::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS], + 'expectation' => [ + ['label' => 'Option 1', 'count' => 1], + ['label' => 'Option 2', 'count' => 1], + ], + ], + 'used_in_navigation_without_results' => [ + 'products_data' => [ + 'bundle-product' => 'Option 1', + 'bundle-product-dropdown-options' => 'Option 2', + ], + 'attribute_data' => ['is_filterable' => 2], + 'expectation' => [ + ['label' => 'Option 1', 'count' => 1], + ['label' => 'Option 2', 'count' => 1], + ['label' => 'Option 3', 'count' => 0], + ], + ], + ]; + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_CATEGORY; + } + + /** + * @inheritdoc + */ + protected function getAttributeCode(): string + { + return 'dropdown_attribute'; + } +} diff --git a/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/Bundle/PriceFilterTest.php b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/Bundle/PriceFilterTest.php new file mode 100644 index 0000000000000..435dd29e16dfa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/LayeredNavigation/Block/Navigation/Search/Bundle/PriceFilterTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\LayeredNavigation\Block\Navigation\Search\Bundle; + +use Magento\Catalog\Model\Layer\Resolver; +use Magento\LayeredNavigation\Block\Navigation\Category\Bundle\PriceFilterTest as CategoryFilterTest; + +/** + * Provides price filter tests for bundle product in navigation block on search page. + * + * @magentoAppArea frontend + * @magentoAppIsolation enabled + * @magentoDbIsolation disabled + */ +class PriceFilterTest extends CategoryFilterTest +{ + /** + * @magentoDataFixture Magento/Bundle/_files/dynamic_and_fixed_bundle_products_in_category.php + * @magentoConfigFixture current_store catalog/layered_navigation/price_range_calculation manual + * @magentoConfigFixture current_store catalog/layered_navigation/price_range_step 10 + * @return void + */ + public function testGetFilters(): void + { + $this->getSearchFiltersAndAssert( + ['bundle-product' => 20.00], + ['is_filterable_in_search' => 1], + [ + ['label' => '$10.00 - $19.99', 'value' => '10-20', 'count' => 1], + ['label' => '$20.00 and above', 'value' => '20-', 'count' => 1], + ] + ); + } + + /** + * @inheritdoc + */ + protected function getLayerType(): string + { + return Resolver::CATALOG_LAYER_SEARCH; + } + + /** + * @inheritdoc + */ + protected function getSearchString(): string + { + return 'Bundle'; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Block/Account/LinkTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Account/LinkTest.php new file mode 100644 index 0000000000000..6dac22bd49384 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Block/Account/LinkTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Block\Account; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Result\Page; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks Newsletter Subscriptions link displaying in account dashboard + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class LinkTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Page */ + private $page; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->page = $this->objectManager->create(Page::class); + } + + /** + * @return void + */ + public function testNewsletterLink(): void + { + $this->preparePage(); + $block = $this->page->getLayout()->getBlock('customer-account-navigation-newsletter-subscriptions-link'); + $this->assertNotFalse($block); + $html = $block->toHtml(); + $this->assertContains('newsletter/manage/', $html); + $this->assertEquals('Newsletter Subscriptions', strip_tags($html)); + } + + /** + * @magentoConfigFixture current_store newsletter/general/active 0 + * + * @return void + */ + public function testNewsletterLinkDisabled(): void + { + $this->preparePage(); + $block = $this->page->getLayout()->getBlock('customer-account-navigation-newsletter-subscriptions-link'); + $this->assertFalse($block); + } + + /** + * Prepare page before render + * + * @return void + */ + private function preparePage(): void + { + $this->page->addHandle([ + 'default', + 'customer_account', + ]); + $this->page->getLayout()->generateXml(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Ajax/StatusTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Ajax/StatusTest.php new file mode 100755 index 0000000000000..3d16cb27e8668 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Ajax/StatusTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Controller\Ajax; + +use Magento\Framework\Serialize\SerializerInterface; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Test Subscriber status ajax + */ +class StatusTest extends AbstractController +{ + /** + * @var SerializerInterface + */ + private $json; + + /** + * @inheritDoc + */ + protected function setUp() + { + parent::setUp(); + $this->json = $this->_objectManager->get(SerializerInterface::class); + } + + /** + * Check newsletter subscription status verification + * + * @magentoDataFixture Magento/Newsletter/_files/subscribers.php + * @dataProvider ajaxSubscriberDataProvider + * @param string $expStatus + * @param string $email + * + * @return void + */ + public function testExecute(string $expStatus, string $email): void + { + $this->getRequest()->setParam('email', $email); + $this->dispatch('newsletter/ajax/status'); + $actual = $this->json->unserialize($this->getResponse()->getBody()); + + $this->assertEquals($expStatus, $actual['subscribed']); + } + + /** + * Provides data and Expected Result + * + * @param void + * @return array + */ + public function ajaxSubscriberDataProvider(): array + { + return [ + 'empty_email_parameter' => [false, ''], + 'invalid_email' => [false, 'invalid_email.com'], + 'unsubscribed_email' => [false, 'sample@email.com'], + 'subscribed_guest_email' => [true, 'customer_two@example.com'], + 'subscribed_registered_customer_email' => [false, 'customer@example.com'], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Manage/SaveTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Manage/SaveTest.php new file mode 100644 index 0000000000000..87b022c942318 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Manage/SaveTest.php @@ -0,0 +1,157 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Controller\Manage; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\Session; +use Magento\Framework\Data\Form\FormKey; +use Magento\Framework\Message\MessageInterface; +use Magento\Newsletter\Model\Plugin\CustomerPlugin; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * Class checks customer subscription + * + * @magentoDbIsolation enabled + */ +class SaveTest extends AbstractController +{ + /** @var Session */ + protected $customerSession; + + /** @var CustomerRepositoryInterface */ + private $customerRepository; + + /** @var FormKey */ + private $formKey; + + /** @var CustomerRegistry */ + private $customerRegistry; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->customerSession = $this->_objectManager->get(Session::class); + $this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class); + $this->formKey = $this->_objectManager->get(FormKey::class); + $this->customerRegistry = $this->_objectManager->get(CustomerRegistry::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->logout(); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Customer/_files/new_customer.php + * + * @dataProvider subscriptionDataProvider + * + * @param bool $isSubscribed + * @param string $expectedMessage + * @return void + */ + public function testSaveAction(bool $isSubscribed, string $expectedMessage): void + { + $this->loginCustomer('new_customer@example.com'); + $this->_objectManager->removeSharedInstance(CustomerPlugin::class); + $this->dispatchSaveAction($isSubscribed); + $this->assertSuccessSubscription($expectedMessage); + } + + /** + * @return array + */ + public function subscriptionDataProvider(): array + { + return [ + 'subscribe_customer' => [ + 'is_subscribed' => true, + 'expected_message' => 'We have saved your subscription.', + ], + 'unsubscribe_customer' => [ + 'is_subscribed' => false, + 'expected_message' => 'We have updated your subscription.', + ], + ]; + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer_confirmation_config_enable.php + * @magentoDataFixture Magento/Customer/_files/new_customer.php + * + * @return void + */ + public function testSubscribeWithEnabledConfirmation(): void + { + $this->loginCustomer('new_customer@example.com'); + $this->dispatchSaveAction(true); + $this->assertSuccessSubscription('A confirmation request has been sent.'); + } + + /** + * @magentoDataFixture Magento/Newsletter/_files/customer_with_subscription.php + * + * @return void + */ + public function testUnsubscribeSubscribedCustomer(): void + { + $this->loginCustomer('new_customer@example.com'); + $this->_objectManager->removeSharedInstance(CustomerPlugin::class); + $this->dispatchSaveAction(false); + $this->assertSuccessSubscription('We have removed your newsletter subscription.'); + } + + /** + * Dispatch save action with parameters + * + * @param string $isSubscribed + * @return void + */ + private function dispatchSaveAction(bool $isSubscribed): void + { + $this->_objectManager->removeSharedInstance(CustomerPlugin::class); + $this->getRequest()->setParam('form_key', $this->formKey->getFormKey()) + ->setParam('is_subscribed', $isSubscribed); + $this->dispatch('newsletter/manage/save'); + } + + /** + * Login customer by email + * + * @param string $email + * @return void + */ + private function loginCustomer(string $email): void + { + $customer = $this->customerRepository->get($email); + $this->customerSession->loginById($customer->getId()); + } + + /** + * Assert that action was successfully done + * + * @param string $expectedMessage + * @return void + */ + private function assertSuccessSubscription(string $expectedMessage): void + { + $this->assertRedirect($this->stringContains('customer/account/')); + $this->assertSessionMessages($this->equalTo([(string)__($expectedMessage)]), MessageInterface::TYPE_SUCCESS); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/ManageTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/ManageTest.php deleted file mode 100644 index 175c1c7c6c668..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/ManageTest.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Newsletter\Controller; - -/** - * @magentoDbIsolation enabled - */ -class ManageTest extends \Magento\TestFramework\TestCase\AbstractController -{ - /** - * @var \Magento\Customer\Model\Session - */ - protected $customerSession; - - /** - * @var \Magento\Framework\Session\Generic - */ - protected $coreSession; - - /** - * Test setup - */ - protected function setUp() - { - parent::setUp(); - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->customerSession = $objectManager->get(\Magento\Customer\Model\Session::class); - $this->customerSession->setCustomerId(1); - $this->coreSession = $objectManager->get(\Magento\Framework\Session\Generic::class); - $this->coreSession->setData('_form_key', 'formKey'); - } - - /** - * test tearDown - */ - protected function tearDown() - { - $this->customerSession->setCustomerId(null); - $this->coreSession->unsetData('_form_key'); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testSaveAction() - { - $this->getRequest() - ->setParam('form_key', 'formKey') - ->setParam('is_subscribed', '1'); - $this->dispatch('newsletter/manage/save'); - - $this->assertRedirect($this->stringContains('customer/account/')); - - /** - * Check that errors - */ - $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR); - - /** - * Check that success message - */ - $this->assertSessionMessages( - $this->equalTo(['We have saved your subscription.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testSaveActionRemoveSubscription() - { - - $this->getRequest() - ->setParam('form_key', 'formKey') - ->setParam('is_subscribed', '0'); - $this->dispatch('newsletter/manage/save'); - - $this->assertRedirect($this->stringContains('customer/account/')); - - /** - * Check that errors - */ - $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR); - - /** - * Check that success message - */ - $this->assertSessionMessages( - $this->equalTo(['We have updated your subscription.']), - \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS - ); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Subscriber/NewActionTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Subscriber/NewActionTest.php new file mode 100644 index 0000000000000..0f07d8b31d13b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/Subscriber/NewActionTest.php @@ -0,0 +1,255 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Newsletter\Controller\Subscriber; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Url; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Newsletter\Model\ResourceModel\Subscriber as SubscriberResource; +use Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory; +use Magento\TestFramework\TestCase\AbstractController; +use Zend\Stdlib\Parameters; + +/** + * Class checks subscription behaviour from frontend + * + * @magentoDbIsolation enabled + * @see \Magento\Newsletter\Controller\Subscriber\NewAction + */ +class NewActionTest extends AbstractController +{ + /** @var Session */ + private $session; + + /** @var CollectionFactory */ + private $subscriberCollectionFactory; + + /** @var SubscriberResource */ + private $subscriberResource; + + /** @var string|null */ + private $subscriberToDelete; + + /** @var CustomerRepositoryInterface */ + private $customerRepository; + + /** @var Url */ + private $customerUrl; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->session = $this->_objectManager->get(Session::class); + $this->subscriberCollectionFactory = $this->_objectManager->get(CollectionFactory::class); + $this->subscriberResource = $this->_objectManager->get(SubscriberResource::class); + $this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class); + $this->customerUrl = $this->_objectManager->get(Url::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + if ($this->subscriberToDelete) { + $this->deleteSubscriber($this->subscriberToDelete); + } + + parent::tearDown(); + } + + /** + * @dataProvider subscribersDataProvider + * + * @param string $email + * @param string $expectedMessage + * @return void + */ + public function testNewAction(string $email, string $expectedMessage): void + { + $this->subscriberToDelete = $email ? $email : null; + $this->prepareRequest($email); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts($expectedMessage); + } + + /** + * @return array + */ + public function subscribersDataProvider(): array + { + return [ + 'without_email' => [ + 'email' => '', + 'message' => '', + ], + 'with_unused_email' => [ + 'email' => 'not_used@example.com', + 'message' => 'Thank you for your subscription.', + ], + 'with_invalid_email' => [ + 'email' => 'invalid_email.com', + 'message' => 'Please enter a valid email address.' + ], + ]; + } + + /** + * @magentoDataFixture Magento/Customer/_files/new_customer.php + * + * @return void + */ + public function testNewActionUsedEmail(): void + { + $this->prepareRequest('new_customer@example.com'); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts('Thank you for your subscription.'); + } + + /** + * @magentoDataFixture Magento/Customer/_files/new_customer.php + * + * @return void + */ + public function testNewActionOwnerEmail(): void + { + $this->prepareRequest('new_customer@example.com'); + $this->session->loginById(1); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts('Thank you for your subscription.'); + } + + /** + * @magentoDataFixture Magento/Newsletter/_files/customer_with_subscription.php + * + * @return void + */ + public function testAlreadyExistEmail(): void + { + $this->prepareRequest('new_customer@example.com'); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts('This email address is already subscribed.'); + } + + /** + * @magentoConfigFixture current_store newsletter/subscription/allow_guest_subscribe 0 + * + * @return void + */ + public function testWithNotAllowedGuestSubscription(): void + { + $message = sprintf( + 'Sorry, but the administrator denied subscription for guests. Please <a href="%s">register</a>.', + $this->customerUrl->getRegisterUrl() + ); + $this->subscriberToDelete = 'guest@example.com'; + $this->prepareRequest('guest@example.com'); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts($message); + } + + /** + * @magentoConfigFixture current_store newsletter/subscription/allow_guest_subscribe 0 + * + * @magentoDataFixture Magento/Customer/_files/new_customer.php + * + * @return void + */ + public function testCustomerSubscribeUnrelatedEmailWithNotAllowedGuestSubscription(): void + { + $this->markTestSkipped('Blocked by MC-31662'); + $this->subscriberToDelete = 'guest@example.com'; + $this->session->loginById($this->customerRepository->get('new_customer@example.com')->getId()); + $this->prepareRequest('guest@example.com'); + $this->dispatch('newsletter/subscriber/new'); + //ToDo message need to be specified after bug MC-31662 fixing + $this->performAsserts(''); + } + + /** + * @magentoConfigFixture current_store newsletter/subscription/confirm 1 + * + * @return void + */ + public function testWithRequiredConfirmation(): void + { + $this->subscriberToDelete = 'guest@example.com'; + $this->prepareRequest('guest@example.com'); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts('The confirmation request has been sent.'); + } + + /** + * @magentoDataFixture Magento/Newsletter/_files/three_subscribers.php + * + * @return void + */ + public function testWithEmailAssignedToAnotherCustomer(): void + { + $this->session->loginById(1); + $this->prepareRequest('customer2@search.example.com'); + $this->dispatch('newsletter/subscriber/new'); + + $this->performAsserts('This email address is already assigned to another user.'); + } + + /** + * Prepare request + * + * @param string $email + * @return void + */ + private function prepareRequest(string $email): void + { + $parameters = $this->_objectManager->create(Parameters::class); + $parameters->set('HTTP_REFERER', 'http://localhost/testRedirect'); + $this->getRequest()->setServer($parameters); + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['email' => $email]); + } + + /** + * Assert session message and expected redirect + * + * @param string $message + * @return void + */ + private function performAsserts(string $message): void + { + if ($message) { + $this->assertSessionMessages($this->equalTo([(string)__($message)])); + } + $this->assertRedirect($this->equalTo('http://localhost/testRedirect')); + } + + /** + * Delete subscribers by email + * + * @param string $email + * @return void + */ + private function deleteSubscriber(string $email): void + { + $collection = $this->subscriberCollectionFactory->create(); + $item = $collection->addFieldToFilter('subscriber_email', $email)->setPageSize(1)->getFirstItem(); + if ($item->getId()) { + $this->subscriberResource->delete($item); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/SubscriberTest.php index bf19d6ddefc36..ec6ae77c385fd 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Controller/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Controller/SubscriberTest.php @@ -23,59 +23,6 @@ */ class SubscriberTest extends AbstractController { - public function testNewAction() - { - $this->getRequest()->setMethod('POST'); - - $this->dispatch('newsletter/subscriber/new'); - - $this->assertSessionMessages($this->isEmpty()); - $this->assertRedirect($this->anything()); - } - - /** - * @magentoDbIsolation enabled - */ - public function testNewActionUnusedEmail() - { - $this->getRequest()->setMethod('POST'); - $this->getRequest()->setPostValue(['email' => 'not_used@example.com']); - - $this->dispatch('newsletter/subscriber/new'); - - $this->assertSessionMessages($this->equalTo(['Thank you for your subscription.'])); - $this->assertRedirect($this->anything()); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testNewActionUsedEmail() - { - $this->getRequest()->setMethod('POST'); - $this->getRequest()->setPostValue(['email' => 'customer@example.com']); - - $this->dispatch('newsletter/subscriber/new'); - - $this->assertSessionMessages($this->equalTo(['Thank you for your subscription.'])); - $this->assertRedirect($this->anything()); - } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - */ - public function testNewActionOwnerEmail() - { - $this->getRequest()->setMethod('POST'); - $this->getRequest()->setPostValue(['email' => 'customer@example.com']); - $this->login(1); - - $this->dispatch('newsletter/subscriber/new'); - - $this->assertSessionMessages($this->equalTo(['Thank you for your subscription.'])); - $this->assertRedirect($this->anything()); - } - /** * Check that Customer still subscribed for newsletters emails after registration. * @@ -149,18 +96,4 @@ private function fillRequestWithAccountDataAndFormKey($email) ->setPostValue('create_address', true) ->setParam('form_key', Bootstrap::getObjectManager()->get(FormKey::class)->getFormKey()); } - - /** - * Login the user - * - * @param string $customerId Customer to mark as logged in for the session - * @return void - */ - protected function login($customerId) - { - /** @var \Magento\Customer\Model\Session $session */ - $session = Bootstrap::getObjectManager() - ->get(\Magento\Customer\Model\Session::class); - $session->loginById($customerId); - } } diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php index bdcbdc035d2b0..06c8902f45897 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php @@ -3,104 +3,175 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Newsletter\Model; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Mail\Template\TransportBuilderMock; +use PHPUnit\Framework\TestCase; /** - * \Magento\Newsletter\Model\Subscriber tests + * Class checks subscription behavior. + * + * @see \Magento\Newsletter\Model\Subscriber */ -class SubscriberTest extends \PHPUnit\Framework\TestCase +class SubscriberTest extends TestCase { + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var SubscriberFactory */ + private $subscriberFactory; + + /** @var TransportBuilderMock */ + private $transportBuilder; + + /** @var CustomerRepositoryInterface */ + private $customerRepository; + /** - * @var Subscriber + * @inheritdoc */ - private $model; - protected function setUp() { - $this->model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Newsletter\Model\Subscriber::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->subscriberFactory = $this->objectManager->get(SubscriberFactory::class); + $this->transportBuilder = $this->objectManager->get(TransportBuilderMock::class); + $this->customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); } /** - * @magentoDataFixture Magento/Newsletter/_files/subscribers.php * @magentoConfigFixture current_store newsletter/subscription/confirm 1 + * + * @magentoDataFixture Magento/Newsletter/_files/subscribers.php + * + * @return void */ - public function testEmailConfirmation() + public function testEmailConfirmation(): void { - $this->model->subscribe('customer_confirm@example.com'); - /** @var TransportBuilderMock $transportBuilder */ - $transportBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->get(\Magento\TestFramework\Mail\Template\TransportBuilderMock::class); + $subscriber = $this->subscriberFactory->create(); + $subscriber->subscribe('customer_confirm@example.com'); // confirmationCode 'ysayquyajua23iq29gxwu2eax2qb6gvy' is taken from fixture $this->assertContains( - '/newsletter/subscriber/confirm/id/' . $this->model->getSubscriberId() + '/newsletter/subscriber/confirm/id/' . $subscriber->getSubscriberId() . '/code/ysayquyajua23iq29gxwu2eax2qb6gvy', - $transportBuilder->getSentMessage()->getBody()->getParts()[0]->getRawContent() + $this->transportBuilder->getSentMessage()->getBody()->getParts()[0]->getRawContent() ); - $this->assertEquals(Subscriber::STATUS_NOT_ACTIVE, $this->model->getSubscriberStatus()); + $this->assertEquals(Subscriber::STATUS_NOT_ACTIVE, $subscriber->getSubscriberStatus()); } /** * @magentoDataFixture Magento/Newsletter/_files/subscribers.php + * + * @return void */ - public function testLoadByCustomerId() + public function testLoadByCustomerId(): void { - $this->assertSame($this->model, $this->model->loadByCustomerId(1)); - $this->assertEquals('customer@example.com', $this->model->getSubscriberEmail()); + $subscriber = $this->subscriberFactory->create(); + $this->assertSame($subscriber, $subscriber->loadByCustomerId(1)); + $this->assertEquals('customer@example.com', $subscriber->getSubscriberEmail()); } /** * @magentoDataFixture Magento/Newsletter/_files/subscribers.php - * @magentoAppArea frontend + * + * @magentoAppArea frontend + * + * @return void */ - public function testUnsubscribeSubscribe() + public function testUnsubscribeSubscribe(): void { - // Unsubscribe and verify - $this->assertSame($this->model, $this->model->loadByCustomerId(1)); - $this->assertEquals($this->model, $this->model->unsubscribe()); - $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $this->model->getSubscriberStatus()); - + $subscriber = $this->subscriberFactory->create(); + $this->assertSame($subscriber, $subscriber->loadByCustomerId(1)); + $this->assertEquals($subscriber, $subscriber->unsubscribe()); + $this->assertContains( + 'You have been unsubscribed from the newsletter.', + $this->transportBuilder->getSentMessage()->getRawMessage() + ); + $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); // Subscribe and verify - $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $this->model->subscribe('customer@example.com')); - $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $this->model->getSubscriberStatus()); + $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->subscribe('customer@example.com')); + $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); + $this->assertContains( + 'You have been successfully subscribed to our newsletter.', + $this->transportBuilder->getSentMessage()->getRawMessage() + ); } /** * @magentoDataFixture Magento/Newsletter/_files/subscribers.php - * @magentoAppArea frontend + * + * @magentoAppArea frontend + * + * @return void */ - public function testUnsubscribeSubscribeByCustomerId() + public function testUnsubscribeSubscribeByCustomerId(): void { + $subscriber = $this->subscriberFactory->create(); // Unsubscribe and verify - $this->assertSame($this->model, $this->model->unsubscribeCustomerById(1)); - $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $this->model->getSubscriberStatus()); - + $this->assertSame($subscriber, $subscriber->unsubscribeCustomerById(1)); + $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $subscriber->getSubscriberStatus()); + $this->assertContains( + 'You have been unsubscribed from the newsletter.', + $this->transportBuilder->getSentMessage()->getRawMessage() + ); // Subscribe and verify - $this->assertSame($this->model, $this->model->subscribeCustomerById(1)); - $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $this->model->getSubscriberStatus()); + $this->assertSame($subscriber, $subscriber->subscribeCustomerById(1)); + $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getSubscriberStatus()); + $this->assertContains( + 'You have been successfully subscribed to our newsletter.', + $this->transportBuilder->getSentMessage()->getRawMessage() + ); } /** - * @magentoDataFixture Magento/Newsletter/_files/subscribers.php * @magentoConfigFixture current_store newsletter/subscription/confirm 1 + * + * @magentoDataFixture Magento/Newsletter/_files/subscribers.php + * + * @return void */ - public function testConfirm() + public function testConfirm(): void { + $subscriber = $this->subscriberFactory->create(); $customerEmail = 'customer_confirm@example.com'; - $this->model->subscribe($customerEmail); - $this->model->loadByEmail($customerEmail); - $this->model->confirm($this->model->getSubscriberConfirmCode()); - - $transportBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\TestFramework\Mail\Template\TransportBuilderMock::class - ); - + $subscriber->subscribe($customerEmail); + $subscriber->loadByEmail($customerEmail); + $subscriber->confirm($subscriber->getSubscriberConfirmCode()); $this->assertContains( 'You have been successfully subscribed to our newsletter.', - $transportBuilder->getSentMessage()->getBody()->getParts()[0]->getRawContent() + $this->transportBuilder->getSentMessage()->getRawMessage() ); } + + /** + * @magentoDataFixture Magento/Customer/_files/customer_confirmation_config_enable.php + * @magentoDataFixture Magento/Newsletter/_files/newsletter_unconfirmed_customer.php + * + * @return void + */ + public function testSubscribeUnconfirmedCustomerWithSubscription(): void + { + $customer = $this->customerRepository->get('unconfirmedcustomer@example.com'); + $subscriber = $this->subscriberFactory->create(); + $subscriber->subscribeCustomerById($customer->getId()); + $this->assertEquals(Subscriber::STATUS_SUBSCRIBED, $subscriber->getStatus()); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer_confirmation_config_enable.php + * @magentoDataFixture Magento/Customer/_files/unconfirmed_customer.php + * + * @return void + */ + public function testSubscribeUnconfirmedCustomerWithoutSubscription(): void + { + $customer = $this->customerRepository->get('unconfirmedcustomer@example.com'); + $subscriber = $this->subscriberFactory->create(); + $subscriber->subscribeCustomerById($customer->getId()); + $this->assertEquals(Subscriber::STATUS_UNCONFIRMED, $subscriber->getStatus()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription.php new file mode 100644 index 0000000000000..f700889881e8d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Newsletter\Model\SubscriberFactory; + +require __DIR__ . '/../../../Magento/Customer/_files/new_customer.php'; + +$subscriberFactory = $objectManager->get(SubscriberFactory::class); +$subscriberFactory->create()->subscribe('new_customer@example.com'); diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription_rollback.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription_rollback.php new file mode 100644 index 0000000000000..145f6a9b43bbb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/customer_with_subscription_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/../../../Magento/Customer/_files/new_customer_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer.php new file mode 100644 index 0000000000000..405ac1c67bd7b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Newsletter\Model\SubscriberFactory; + +require __DIR__ . '/../../../Magento/Customer/_files/unconfirmed_customer.php'; + +/** @var SubscriberFactory $subscriberFactory */ +$subscriberFactory = $objectManager->get(SubscriberFactory::class); +$subscriberFactory->create()->subscribe('unconfirmedcustomer@example.com'); diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer_rollback.php new file mode 100644 index 0000000000000..5742526988187 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/newsletter_unconfirmed_customer_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/../../../Magento/Customer/_files/unconfirmed_customer_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers.php new file mode 100644 index 0000000000000..5eb0ec5843bd8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Newsletter\Model\SubscriberFactory; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Customer/_files/three_customers.php'; + +$objectManager = Bootstrap::getObjectManager(); +$subscriberFactory = $objectManager->get(SubscriberFactory::class); + +$subscriberFactory->create()->subscribe('customer@search.example.com'); +$subscriberFactory->create()->subscribe('customer2@search.example.com'); +$subscriberFactory->create()->subscribe('customer3@search.example.com'); diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers_rollback.php b/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers_rollback.php new file mode 100644 index 0000000000000..e1760db7b1e52 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/../../../Magento/Customer/_files/three_customers_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price.php new file mode 100644 index 0000000000000..337f4e4f9b1ef --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** + * @var Tablerate $resourceModel + */ +$resourceModel = $objectManager->create(Tablerate::class); +$tableRatesData = [ + [ + 'website_id' => 1, + 'dest_country_id' => 'US', + 'dest_region_id' => 0, + 'dest_zip' => '*', + 'condition_name' => 'package_value_with_discount', + 'condition_value' => 0.00, + 'price' => 15, + 'cost' => 0 + ], + [ + 'website_id' => 1, + 'dest_country_id' => 'US', + 'dest_region_id' => 0, + 'dest_zip' => '*', + 'condition_name' => 'package_value_with_discount', + 'condition_value' => 50.00, + 'price' => 10, + 'cost' => 0 + ], + [ + 'website_id' => 1, + 'dest_country_id' => 'US', + 'dest_region_id' => 0, + 'dest_zip' => '*', + 'condition_name' => 'package_value_with_discount', + 'condition_value' => 100.00, + 'price' => 5, + 'cost' => 0 + ] + ]; +$columns = [ + 'website_id', + 'dest_country_id', + 'dest_region_id', + 'dest_zip', + 'condition_name', + 'condition_value', + 'price', + 'cost' +]; +$resourceModel->getConnection()->insertArray($resourceModel->getMainTable(), $columns, $tableRatesData); diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price_rollback.php new file mode 100644 index 0000000000000..ca1971033dea0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_price_rollback.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +$resourceModel = $objectManager->create(Tablerate::class); +$resourceModel->getConnection()->delete($resourceModel->getMainTable()); diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php index 1a4e640a1eabe..c080d7a3ab229 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php @@ -6,24 +6,24 @@ namespace Magento\Quote\Model; -use Magento\Customer\Model\Vat; -use Magento\Store\Model\ScopeInterface; -use Magento\Tax\Model\Config as TaxConfig; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId; -use Magento\Framework\ObjectManagerInterface; -use Magento\Customer\Api\Data\GroupInterface; -use Magento\Customer\Api\GroupRepositoryInterface; -use Magento\Tax\Model\ClassModel; -use Magento\Framework\App\Config\MutableScopeConfigInterface; use Magento\Customer\Api\AddressRepositoryInterface; -use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Quote\Api\ShippingMethodManagementInterface; use Magento\Customer\Api\Data\AddressInterface; +use Magento\Customer\Api\Data\GroupInterface; +use Magento\Customer\Api\GroupRepositoryInterface; +use Magento\Customer\Model\Vat; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Tax\Api\TaxClassRepositoryInterface; +use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\ShippingMethodManagementInterface; +use Magento\Store\Model\ScopeInterface; use Magento\Tax\Api\Data\TaxClassInterface; +use Magento\Tax\Api\TaxClassRepositoryInterface; +use Magento\Tax\Model\ClassModel; +use Magento\Tax\Model\Config as TaxConfig; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId; /** * Test for shipping methods management @@ -56,6 +56,7 @@ protected function setUp() * @magentoDataFixture Magento/SalesRule/_files/cart_rule_100_percent_off.php * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php * @return void + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function testRateAppliedToShipping(): void { @@ -118,6 +119,71 @@ public function testTableRateFreeShipping() } } + /** + * Test table rate amount for the cart that contains some items with free shipping applied. + * + * @magentoConfigFixture current_store carriers/tablerate/active 1 + * @magentoConfigFixture current_store carriers/flatrate/active 0 + * @magentoConfigFixture current_store carriers/freeshipping/active 0 + * @magentoConfigFixture current_store carriers/tablerate/condition_name package_value_with_discount + * @magentoDataFixture Magento/Catalog/_files/categories.php + * @magentoDataFixture Magento/SalesRule/_files/cart_rule_free_shipping_by_category.php + * @magentoDataFixture Magento/Sales/_files/quote_with_multiple_products.php + * @magentoDataFixture Magento/OfflineShipping/_files/tablerates_price.php + * @return void + */ + public function testTableRateWithCartRuleForFreeShipping() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $quote = $this->getQuote('tableRate'); + $cartId = $quote->getId(); + if (!$cartId) { + $this->fail('quote fixture failed'); + } + /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ + $quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class) + ->create(); + $quoteIdMask->load($cartId, 'quote_id'); + //Use masked cart Id + $cartId = $quoteIdMask->getMaskedId(); + $addressFactory = $this->objectManager->get(\Magento\Quote\Api\Data\AddressInterfaceFactory::class); + /** @var \Magento\Quote\Api\Data\AddressInterface $address */ + $address = $addressFactory->create(); + $address->setCountryId('US'); + /** @var \Magento\Quote\Api\GuestShippingMethodManagementInterface $shippingEstimation */ + $shippingEstimation = $objectManager->get(\Magento\Quote\Api\GuestShippingMethodManagementInterface::class); + $result = $shippingEstimation->estimateByExtendedAddress($cartId, $address); + $this->assertCount(1, $result); + $rate = reset($result); + $expectedResult = [ + 'method_code' => 'bestway', + 'amount' => 10 + ]; + $this->assertEquals($expectedResult['method_code'], $rate->getMethodCode()); + $this->assertEquals($expectedResult['amount'], $rate->getAmount()); + } + + /** + * Retrieves quote by reserved order id. + * + * @param string $reservedOrderId + * @return Quote + */ + private function getQuote(string $reservedOrderId): Quote + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId) + ->create(); + + /** @var CartRepositoryInterface $quoteRepository */ + $quoteRepository = $this->objectManager->get(CartRepositoryInterface::class); + $items = $quoteRepository->getList($searchCriteria)->getItems(); + + return array_pop($items); + } + /** * @magentoConfigFixture current_store carriers/tablerate/active 1 * @magentoConfigFixture current_store carriers/tablerate/condition_name package_qty diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php index 6dba48092c400..2ac14fbdc68cc 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/SaveTest.php @@ -68,6 +68,14 @@ protected function setUp() */ public function testExecuteWithPaymentOperation() { + /** @var OrderService|MockObject $orderService */ + $orderService = $this->getMockBuilder(OrderService::class) + ->disableOriginalConstructor() + ->getMock(); + $orderService->method('place') + ->willThrowException(new LocalizedException(__('Transaction has been declined.'))); + $this->_objectManager->addSharedInstance($orderService, OrderService::class); + $quote = $this->getQuote('2000000001'); $session = $this->_objectManager->get(Quote::class); $session->setQuoteId($quote->getId()); @@ -82,14 +90,6 @@ public function testExecuteWithPaymentOperation() $this->getRequest()->setMethod(Http::METHOD_POST); $this->getRequest()->setPostValue(['order' => $data]); - /** @var OrderService|MockObject $orderService */ - $orderService = $this->getMockBuilder(OrderService::class) - ->disableOriginalConstructor() - ->getMock(); - $orderService->method('place') - ->willThrowException(new LocalizedException(__('Transaction has been declined.'))); - $this->_objectManager->addSharedInstance($orderService, OrderService::class); - $this->dispatch('backend/sales/order_create/save'); $this->assertSessionMessages( self::equalTo(['Transaction has been declined.']), diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php index 724865176188a..83bc7e10647b4 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Email/Sender/ShipmentSenderTest.php @@ -10,6 +10,9 @@ /** * @magentoAppArea frontend + * + * @deprecated since ShipmentSender is deprecated + * @see \Magento\Sales\Model\Order\Email\Sender\ShipmentSender */ class ShipmentSenderTest extends \PHPUnit\Framework\TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php new file mode 100644 index 0000000000000..5f5f534ae2cee --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\Order\Creditmemo\Item; +use Magento\Sales\Model\Order\CreditmemoFactory; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/order_with_grouped_product.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$creditmemoFactory = $objectManager->get(CreditmemoFactory::class); +$creditmemo = $creditmemoFactory->createByOrder($order, $order->getData()); +$creditmemo->setOrder($order); +$creditmemo->setState(Creditmemo::STATE_OPEN); +$creditmemo->setIncrementId('100000002'); +$creditmemo->save(); + +$orderItem = current($order->getAllItems()); +$orderItem->setName('Test item') + ->setQtyRefunded(1) + ->setQtyInvoiced(10) + ->setOriginalPrice(20); + +$creditItem = $objectManager->get(Item::class); +$creditItem->setCreditmemo($creditmemo) + ->setName('Creditmemo item') + ->setOrderItemId($orderItem->getId()) + ->setQty(1) + ->setPrice(20) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php new file mode 100644 index 0000000000000..c8420f8a252ca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\ResourceModel\Order\Creditmemo\Collection; +use Magento\TestFramework\Helper\Bootstrap; + +require 'default_rollback.php'; + +/** @var $creditmemo Creditmemo */ +$creditmemoCollection = Bootstrap::getObjectManager()->create(Collection::class); +foreach ($creditmemoCollection as $creditmemo) { + $creditmemo->delete(); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice.php new file mode 100644 index 0000000000000..06ddb18b009d1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\DB\Transaction; +use Magento\Framework\Stdlib\DateTime; +use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\Sales\Api\InvoiceManagementInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\OrderFactory; + +require __DIR__ . '/order.php'; + +/** @var OrderFactory $orderFactory */ +$orderFactory = $objectManager->get(OrderInterfaceFactory::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +/** @var InvoiceManagementInterface $invoiceManagement */ +$invoiceManagement = $objectManager->get(InvoiceManagementInterface::class); +/** @var Transaction $transaction */ +$transaction = $objectManager->get(Transaction::class); + +$dateTime = new \DateTimeImmutable(); +$ordersData = [ + [ + 'increment_id' => '100000002', + 'state' => Order::STATE_PROCESSING, + 'status' => 'processing', + 'base_to_global_rate' => 1, + 'base_grand_total' => 120.00, + 'grand_total' => 120.00, + 'subtotal' => 120.00, + 'created_at' => $dateTime->modify('-1 hour')->format(DateTime::DATETIME_PHP_FORMAT), + ], + [ + 'increment_id' => '100000003', + 'state' => Order::STATE_PROCESSING, + 'status' => 'processing', + 'base_to_global_rate' => 1, + 'base_grand_total' => 130.00, + 'grand_total' => 130.00, + 'subtotal' => 130.00, + 'created_at' => $dateTime->modify('-1 day')->format(DateTime::DATETIME_PHP_FORMAT), + ], + [ + 'increment_id' => '100000004', + 'state' => Order::STATE_PROCESSING, + 'status' => 'processing', + 'base_to_global_rate' => 1, + 'base_grand_total' => 140.00, + 'grand_total' => 140.00, + 'subtotal' => 140.00, + 'created_at' => $dateTime->modify('-1 month')->format(DateTime::DATETIME_PHP_FORMAT), + ], + [ + 'increment_id' => '100000005', + 'state' => Order::STATE_PROCESSING, + 'status' => 'processing', + 'base_to_global_rate' => 1, + 'base_grand_total' => 150.00, + 'grand_total' => 150.00, + 'subtotal' => 150.00, + 'created_at' => $dateTime->modify('-1 year')->format(DateTime::DATETIME_PHP_FORMAT), + ], + [ + 'increment_id' => '100000006', + 'state' => Order::STATE_PROCESSING, + 'status' => 'processing', + 'base_to_global_rate' => 1, + 'base_grand_total' => 160.00, + 'grand_total' => 160.00, + 'subtotal' => 160.00, + 'created_at' => $dateTime->modify('-2 year')->format(DateTime::DATETIME_PHP_FORMAT), + ], +]; + +foreach ($ordersData as $orderData) { + /** @var Order $order */ + $order = $orderFactory->create(); + $order + ->setData($orderData) + ->addItem($orderItem) + ->setCustomerIsGuest(true) + ->setCustomerEmail('customer@null.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setPayment($payment); + $orderRepository->save($order); + + /** @var Invoice $invoice */ + $invoice = $invoiceManagement->prepareInvoice($order); + $invoice->register(); + $order->setIsInProcess(true); + $transaction + ->addObject($order) + ->addObject($invoice) + ->save(); +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice_rollback.php new file mode 100644 index 0000000000000..2595d6bf4084a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/default_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php new file mode 100644 index 0000000000000..0cdc2d10e6f06 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Address as OrderAddress; +use Magento\Sales\Model\Order\Item as OrderItem; +use Magento\Sales\Model\Order\Payment; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require 'default_rollback.php'; +require __DIR__ . '/../../../Magento/GroupedProduct/_files/product_grouped_with_simple.php'; +$addressData = include __DIR__ . '/address_data.php'; + +$objectManager = Bootstrap::getObjectManager(); +$billingAddress = $objectManager->create(OrderAddress::class, ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +$payment = $objectManager->create(Payment::class); +$payment->setMethod('checkmo') + ->setAdditionalInformation('last_trans_id', '11122') + ->setAdditionalInformation( + 'metadata', + [ + 'type' => 'free', + 'fraudulent' => false, + ] + ); +$product = $objectManager->get(ProductRepositoryInterface::class)->get('simple_11'); +$orderItem = $objectManager->create(OrderItem::class); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(2) + ->setBasePrice($product->getPrice()) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType('grouped') + ->setName($product->getName()) + ->setSku($product->getSku()); + +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000002') + ->setState(Order::STATE_PROCESSING) + ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)) + ->setSubtotal(100) + ->setGrandTotal(100) + ->setBaseSubtotal(100) + ->setBaseGrandTotal(100) + ->setCustomerIsGuest(true) + ->setCustomerEmail('customer@null.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setStoreId($objectManager->get(StoreManagerInterface::class)->getStore()->getId()) + ->addItem($orderItem) + ->setPayment($payment); +$orderRepository = $objectManager->create(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php new file mode 100644 index 0000000000000..1fb4b4636ab29 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require 'default_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/orders_with_customer.php b/dev/tests/integration/testsuite/Magento/Sales/_files/orders_with_customer.php index 1a0a94b0ca951..4c962d5527c49 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/orders_with_customer.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/orders_with_customer.php @@ -24,7 +24,6 @@ 'base_grand_total' => 120.00, 'store_id' => 1, 'website_id' => 1, - 'payment' => $payment ], [ 'increment_id' => '100000003', @@ -36,7 +35,6 @@ 'total_paid' => 130.00, 'store_id' => 0, 'website_id' => 0, - 'payment' => $payment ], [ 'increment_id' => '100000004', @@ -47,7 +45,6 @@ 'subtotal' => 140.00, 'store_id' => 1, 'website_id' => 1, - 'payment' => $payment ], [ 'increment_id' => '100000005', @@ -59,7 +56,6 @@ 'total_paid' => 150.00, 'store_id' => 1, 'website_id' => 1, - 'payment' => $payment ], [ 'increment_id' => '100000006', @@ -71,7 +67,6 @@ 'total_paid' => 160.00, 'store_id' => 1, 'website_id' => 1, - 'payment' => $payment ], ]; @@ -79,6 +74,8 @@ $orderRepository = $objectManager->create(OrderRepositoryInterface::class); /** @var array $orderData */ foreach ($orders as $orderData) { + $newPayment = clone $payment; + $newPayment->setId(null); /** @var $order \Magento\Sales\Model\Order */ $order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Sales\Model\Order::class @@ -108,7 +105,8 @@ ->setCustomerId(1) ->setCustomerEmail('customer@example.com') ->setBillingAddress($billingAddress) - ->setShippingAddress($shippingAddress); + ->setShippingAddress($shippingAddress) + ->setPayment($newPayment); $orderRepository->save($order); } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_multiple_products.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_multiple_products.php new file mode 100644 index 0000000000000..4164a17ea3a86 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_multiple_products.php @@ -0,0 +1,137 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\QuoteIdMask; +use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\CatalogInventory\Api\Data\StockItemInterface; + +Bootstrap::getInstance()->loadArea('frontend'); +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); +$productRepository = $objectManager + ->create(ProductRepositoryInterface::class); +$firstProduct = $objectManager->create(Product::class); +$firstProduct->setTypeId('simple') + ->setCategoryIds([3]) + ->setId(123) + ->setAttributeSetId(4) + ->setName('First Test Product For TableRate') + ->setSku('simple-tableRate-1') + ->setPrice(30) + ->setTaxClassId(0) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); +/** @var StockItemInterface $stockItem */ +$firstStockItem = $objectManager->create(StockItemInterface::class); +$firstStockItem->setQty(100) + ->setIsInStock(true) + ->setManageStock(true); +$extensionAttributes = $firstProduct->getExtensionAttributes(); +$extensionAttributes->setStockItem($firstStockItem); + +/** @var ProductRepositoryInterface $productRepository */ +$firstProduct = $productRepository->save($firstProduct); + +$secondProduct = $objectManager->create(Product::class); +$secondProduct->setTypeId('simple') + ->setCategoryIds([6]) + ->setId(124) + ->setAttributeSetId(4) + ->setName('Second Test Product For TableRate') + ->setSku('simple-tableRate-2') + ->setPrice(40) + ->setTaxClassId(0) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); +/** @var StockItemInterface $stockItem */ +$secondStockItem = $objectManager->create(StockItemInterface::class); +$secondStockItem->setQty(100) + ->setIsInStock(true) + ->setManageStock(true); +$extensionAttributes = $secondProduct->getExtensionAttributes(); +$extensionAttributes->setStockItem($secondStockItem); + +/** @var ProductRepositoryInterface $productRepository */ +$secondProduct = $productRepository->save($secondProduct); + +$thirdProduct = $objectManager->create(Product::class); +$thirdProduct->setTypeId('simple') + ->setCategoryIds([6]) + ->setId(658) + ->setAttributeSetId(4) + ->setName('Third Test Product For TableRate') + ->setSku('simple-tableRate-3') + ->setPrice(50) + ->setTaxClassId(0) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); +/** @var StockItemInterface $stockItem */ +$thirdStockItem = $objectManager->create(StockItemInterface::class); +$thirdStockItem->setQty(100) + ->setIsInStock(true) + ->setManageStock(true); +$extensionAttributes = $thirdProduct->getExtensionAttributes(); +$extensionAttributes->setStockItem($thirdStockItem); + +/** @var ProductRepositoryInterface $productRepository */ +$thirdProduct = $productRepository->save($thirdProduct); + +$addressData = include __DIR__ . '/address_data.php'; +$billingAddress = $objectManager->create( + Address::class, + ['data' => $addressData] +); +$billingAddress->setAddressType('billing'); +$shippingAddress = $objectManager->create( + Address::class, + ['data' => $addressData] +); +$shippingAddress->setAddressType('shipping'); +$store = $objectManager + ->get(StoreManagerInterface::class) + ->getStore(); + +/** @var Quote $quote */ +$quote = $objectManager->create(Quote::class); +$quote->setCustomerIsGuest(true) + ->setStoreId($store->getId()) + ->setReservedOrderId('tableRate') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress); +$quote->getPayment()->setMethod('checkmo'); +$quote->addProduct($firstProduct); +$quote->addProduct($secondProduct); +$quote->addProduct($thirdProduct); +$quote->setIsMultiShipping(false); +$quoteRepository = $objectManager + ->get(CartRepositoryInterface::class); +$quoteRepository->save($quote); + +/** @var QuoteIdMask $quoteIdMask */ +$quoteIdMask = $objectManager + ->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_multiple_products_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_multiple_products_rollback.php new file mode 100644 index 0000000000000..73801919ab912 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_multiple_products_rollback.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogInventory\Model\StockRegistryStorage; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var $quote Quote */ +$quote = $objectManager->create(Quote::class); +$quote->load('tableRate', 'reserved_order_id'); +if ($quote->getId()) { + $quote->delete(); +} + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager + ->create(ProductRepositoryInterface::class); + +try { + $firstProduct = $productRepository->get('simple-tableRate-1', false, null, true); + $productRepository->delete($firstProduct); +} catch (NoSuchEntityException $exception) { + //Product already removed +} +try { + $secondProduct = $productRepository->get('simple-tableRate-2', false, null, true); + $productRepository->delete($secondProduct); +} catch (NoSuchEntityException $exception) { + //Product already removed +} +try { + $thirdProduct = $productRepository->get('simple-tableRate-3', false, null, true); + $productRepository->delete($thirdProduct); +} catch (NoSuchEntityException $exception) { + //Product already removed +} +/** @var StockRegistryStorage $stockRegistryStorage */ +$stockRegistryStorage = $objectManager + ->get(StockRegistryStorage::class); +$stockRegistryStorage->removeStockItem(123); +$stockRegistryStorage->removeStockItem(124); +$stockRegistryStorage->removeStockItem(658); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category.php new file mode 100644 index 0000000000000..9f973b704e8e6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Customer\Model\GroupManagement; +use Magento\Framework\Registry; +use Magento\SalesRule\Model\Rule; +use Magento\SalesRule\Model\Rule\Condition\Product; +use Magento\SalesRule\Model\Rule\Condition\Product\Combine; +use Magento\SalesRule\Model\RuleFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +$salesRuleFactory = $objectManager->create(RuleFactory::class); +/** @var Rule $salesRule */ +$salesRule = $salesRuleFactory->create(); +$row = + [ + 'name' => 'TableRate Free shipping if category is 3', + 'is_active' => 1, + 'customer_group_ids' => [GroupManagement::NOT_LOGGED_IN_ID], + 'coupon_type' => Rule::COUPON_TYPE_NO_COUPON, + 'conditions' => [ + 1 => [ + 'type' => Rule\Condition\Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + ] + ], + 'actions' => [ + 1 => [ + 'type' => Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => [], + 'actions' => [ + 1 => [ + 'type' => Product::class, + 'attribute' => 'category_ids', + 'operator' => '==', + 'value' => '3', + 'is_value_processed' => false, + 'attribute_scope' => '' + ] + ] + ] + ], + 'is_advanced' => 1, + 'simple_action' => 'by_percent', + 'discount_amount' => 0, + 'stop_rules_processing' => 0, + 'discount_qty' => 0, + 'discount_step' => 0, + 'apply_to_shipping' => 1, + 'times_used' => 0, + 'is_rss' => 1, + 'use_auto_generation' => 0, + 'uses_per_coupon' => 0, + 'simple_free_shipping' => 1, + 'website_ids' => [ + $objectManager->get( + StoreManagerInterface::class + )->getWebsite()->getId() + ] + ]; +$salesRule->loadPost($row); +$salesRule->save(); + +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('cart_rule_free_shipping_by_category'); +$registry->register('cart_rule_free_shipping_by_category', $salesRule); diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category_rollback.php new file mode 100644 index 0000000000000..837e06ea824e2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_free_shipping_by_category_rollback.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Registry; +use Magento\SalesRule\Model\Rule; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var Registry $registry */ +$registry = Bootstrap::getObjectManager()->get(Registry::class); + +/** @var Rule $rule */ +$rule = $registry->registry('cart_rule_free_shipping_by_category'); +if ($rule) { + $rule->delete(); +} diff --git a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock b/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock index 48fa6d0d0cd34..c5529f75b9d05 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock +++ b/dev/tests/integration/testsuite/Magento/Setup/Model/_files/testSkeleton/composer.lock @@ -887,10 +887,6 @@ "app/.htaccess", "app/.htaccess" ], - [ - "app/functions.php", - "app/functions.php" - ], [ "app/autoload.php", "app/autoload.php" diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 623335f7a30d7..cef5c9c6a9c28 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -185,11 +185,13 @@ public function getBaseUrlDataProvider() */ public function testGetBaseUrlInPub() { - \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize([ - Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS => [ - DirectoryList::PUB => [DirectoryList::URL_PATH => ''], - ], - ]); + \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize( + [ + Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS => [ + DirectoryList::PUB => [DirectoryList::URL_PATH => ''], + ], + ] + ); $this->model = $this->_getStoreModel(); $this->model->load('default'); @@ -285,14 +287,14 @@ public function testIsCanDelete() /** * @magentoDataFixture Magento/Store/_files/core_second_third_fixturestore.php - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Catalog/_files/products.php + * @magentoAppIsolation enabled */ public function testGetCurrentUrl() { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class) - ->setValue('web/url/use_store', true, ScopeInterface::SCOPE_STORE, 'secondstore'); + ->setValue('web/url/use_store', true, ScopeInterface::SCOPE_STORE, 'secondstore'); $this->model->load('admin'); $this->model @@ -332,9 +334,10 @@ public function testGetCurrentUrl() } /** - * @magentoDataFixture Magento/Store/_files/second_store.php - * @magentoDataFixture Magento/Catalog/_files/category_product.php - * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Store/_files/core_second_third_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/products.php + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled */ public function testGetCurrentUrlWithUseStoreInUrlFalse() { @@ -343,34 +346,34 @@ public function testGetCurrentUrlWithUseStoreInUrlFalse() ->setValue('web/url/use_store', false, ScopeInterface::SCOPE_STORE, 'default'); /** @var \Magento\Store\Model\Store $secondStore */ - $secondStore = $objectManager->get(StoreRepositoryInterface::class)->get('fixture_second_store'); + $secondStore = $objectManager->get(StoreRepositoryInterface::class)->get('secondstore'); /** @var \Magento\Catalog\Model\ProductRepository $productRepository */ $productRepository = $objectManager->create(ProductRepository::class); - $product = $productRepository->get('simple333'); + $product = $productRepository->get('simple'); $product->setStoreId($secondStore->getId()); $url = $product->getUrlInStore(); /** @var \Magento\Catalog\Model\CategoryRepository $categoryRepository */ $categoryRepository = $objectManager->get(\Magento\Catalog\Model\CategoryRepository::class); - $category = $categoryRepository->get(333, $secondStore->getStoreId()); + $category = $categoryRepository->get(2, $secondStore->getStoreId()); $this->assertEquals( - $secondStore->getBaseUrl() . 'catalog/category/view/s/category-1/id/333/', + $secondStore->getBaseUrl() . 'catalog/category/view/s/default-category/id/2/', $category->getUrl() ); $this->assertEquals( $secondStore->getBaseUrl() . - 'catalog/product/view/id/333/s/simple-product-three/?___store=fixture_second_store', + 'catalog/product/view/id/1/s/simple-product/?___store=secondstore', $url ); $this->assertEquals( - $secondStore->getBaseUrl() . '?___store=fixture_second_store&___from_store=default', + $secondStore->getBaseUrl() . '?___store=secondstore&___from_store=default', $secondStore->getCurrentUrl() ); $this->assertEquals( - $secondStore->getBaseUrl() . '?___store=fixture_second_store', + $secondStore->getBaseUrl() . '?___store=secondstore', $secondStore->getCurrentUrl(false) ); } @@ -382,14 +385,16 @@ public function testGetCurrentUrlWithUseStoreInUrlFalse() */ public function testCRUD() { - $this->model->setData([ - 'code' => 'test', - 'website_id' => 1, - 'group_id' => 1, - 'name' => 'test name', - 'sort_order' => 0, - 'is_active' => 1, - ]); + $this->model->setData( + [ + 'code' => 'test', + 'website_id' => 1, + 'group_id' => 1, + 'name' => 'test name', + 'sort_order' => 0, + 'is_active' => 1, + ] + ); $crud = new \Magento\TestFramework\Entity( $this->model, ['name' => 'new name'], @@ -462,8 +467,8 @@ public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $expectedRe } /** - * @see self::testIsUseStoreInUrl; * @return array + * @see self::testIsUseStoreInUrl; */ public function isUseStoreInUrlDataProvider() { diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/Account/LinkTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Account/LinkTest.php new file mode 100644 index 0000000000000..f4d66b2ff8cde --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Account/LinkTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block\Account; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Result\Page; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks My Wish List link displaying in account dashboard + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class LinkTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Page */ + private $page; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->page = $this->objectManager->create(Page::class); + } + + /** + * @return void + */ + public function testNewsletterLink(): void + { + $this->preparePage(); + $block = $this->page->getLayout()->getBlock('customer-account-navigation-wish-list-link'); + $this->assertNotFalse($block); + $html = $block->toHtml(); + $this->assertContains('wishlist/', $html); + $this->assertEquals('My Wish List', strip_tags($html)); + } + + /** + * @magentoConfigFixture current_store wishlist/general/active 0 + * + * @return void + */ + public function testNewsletterLinkDisabled(): void + { + $this->preparePage(); + $block = $this->page->getLayout()->getBlock('customer-account-navigation-wish-list-link'); + $this->assertFalse($block); + } + + /** + * Prepare page before render + * + * @return void + */ + private function preparePage(): void + { + $this->page->addHandle([ + 'default', + 'customer_account', + ]); + $this->page->getLayout()->generateXml(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/ProductList/Item/AddTo/WishlistTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/ProductList/Item/AddTo/WishlistTest.php new file mode 100644 index 0000000000000..36bd4dd4f312e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/ProductList/Item/AddTo/WishlistTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block\Catalog\Product\ProductList\Item\AddTo; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks add to wishlist button on category page. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + */ +class WishlistTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Wishlist */ + private $block; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class) + ->createBlock(Wishlist::class)->setTemplate('Magento_Wishlist::catalog/product/list/addto/wishlist.phtml'); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testAddToWishListVisible(): void + { + $product = $this->productRepository->get('simple2'); + $html = $this->block->setProduct($product)->toHtml(); + $this->assertEquals('Add to Wish List', trim(strip_tags($html))); + } + + /** + * @magentoConfigFixture current_store wishlist/general/active 0 + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testAddToWishListNotVisible(): void + { + $product = $this->productRepository->get('simple2'); + $this->assertEmpty($this->block->setProduct($product)->toHtml()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/View/AddTo/WishlistTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/View/AddTo/WishlistTest.php new file mode 100644 index 0000000000000..8d0226bfe9a2b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Catalog/Product/View/AddTo/WishlistTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block\Catalog\Product\View\AddTo; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Checks add to wishlist button on product page. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + */ +class WishlistTest extends TestCase +{ + private const ADD_TO_WISHLIST_XPATH = "//a[@data-action='add-to-wishlist']" + . "/span[contains(text(), 'Add to Wish List')]"; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Registry */ + private $registry; + + /** @var Wishlist */ + private $block; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->registry = $this->objectManager->get(Registry::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class) + ->createBlock(Wishlist::class)->setTemplate('Magento_Wishlist::catalog/product/view/addto/wishlist.phtml'); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->registry->unregister('product'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testAddToWishListVisible(): void + { + $product = $this->productRepository->get('simple2'); + $this->registerProduct($product); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(self::ADD_TO_WISHLIST_XPATH, $this->block->toHtml()) + ); + } + + /** + * @magentoConfigFixture current_store wishlist/general/active 0 + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testAddToWishListNotVisible(): void + { + $product = $this->productRepository->get('simple2'); + $this->registerProduct($product); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath(self::ADD_TO_WISHLIST_XPATH, $this->block->toHtml()) + ); + } + + /** + * Register the product. + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/SidebarTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/SidebarTest.php new file mode 100644 index 0000000000000..6e6e88ab73019 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/SidebarTest.php @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block\Customer; + +use Magento\Framework\App\ProductMetadata; +use Magento\Framework\App\ProductMetadataInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Result\Page; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class test sidebar wish list block. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class SidebarTest extends TestCase +{ + private const BLOCK_NAME = 'wishlist_sidebar'; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Page */ + private $page; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $productMetadataInterface = $this->objectManager->get(ProductMetadataInterface::class); + if ($productMetadataInterface->getEdition() !== ProductMetadata::EDITION_NAME) { + $this->markTestSkipped('Skipped, because this logic is rewritten on EE.'); + } + $this->page = $this->objectManager->create(Page::class); + } + + /** + * @magentoConfigFixture current_store wishlist/general/show_in_sidebar 1 + * + * @return void + */ + public function testSidebarWishListVisible(): void + { + $this->preparePageLayout(); + $block = $this->page->getLayout()->getBlock(self::BLOCK_NAME); + $this->assertNotFalse($block); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + "//div[contains(@class, 'block-wishlist')]//strong[contains(text(), 'My Wish List')]", + $block->toHtml() + ) + ); + } + + /** + * @magentoConfigFixture current_store wishlist/general/show_in_sidebar 0 + * + * @return void + */ + public function testSidebarWishListNotVisible(): void + { + $this->preparePageLayout(); + $this->assertFalse( + $this->page->getLayout()->getBlock(self::BLOCK_NAME), + 'Sidebar wish list should not be visible.' + ); + } + + /** + * Prepare category page. + * + * @return void + */ + private function preparePageLayout(): void + { + $this->page->addHandle([ + 'default', + 'catalog_category_view', + ]); + $this->page->getLayout()->generateXml(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/WishlistTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/WishlistTest.php new file mode 100644 index 0000000000000..944d2ac6faada --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/Customer/WishlistTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block\Customer; + +use Magento\Customer\Model\Session; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Result\Page; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Class test my wish list on customer account page. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + */ +class WishlistTest extends TestCase +{ + private const ITEMS_COUNT_XPATH = "//div[contains(@class, 'pager')]//span[contains(@class, 'toolbar-number')" + . " and contains(text(), '%s Item')]"; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Page */ + private $page; + + /** @var Session */ + private $customerSession; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->page = $this->objectManager->create(Page::class); + $this->customerSession = $this->objectManager->get(Session::class); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->customerSession->setCustomerId(null); + + parent::tearDown(); + } + + /** + * @magentoConfigFixture current_store wishlist/wishlist_link/use_qty 0 + * @magentoDataFixture Magento/Wishlist/_files/wishlist_with_product_qty_three.php + * + * @return void + */ + public function testDisplayNumberOfItemsInWishList(): void + { + $this->customerSession->setCustomerId(1); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf(self::ITEMS_COUNT_XPATH, 1), $this->getWishListPagerBlockHtml()) + ); + } + + /** + * @magentoConfigFixture current_store wishlist/wishlist_link/use_qty 1 + * @magentoDataFixture Magento/Wishlist/_files/wishlist_with_product_qty_three.php + * + * @return void + */ + public function testDisplayItemQuantitiesInWishList(): void + { + $this->markTestSkipped('Test is blocked by issue MC-31595'); + $this->customerSession->setCustomerId(1); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath(sprintf(self::ITEMS_COUNT_XPATH, 3), $this->getWishListPagerBlockHtml()) + ); + } + + /** + * Get wish list pager block html. + * + * @return string + */ + private function getWishListPagerBlockHtml(): string + { + $this->page->addHandle([ + 'default', + 'wishlist_index_index', + ]); + $this->page->getLayout()->generateXml(); + /** @var Wishlist $customerWishlistBlock */ + $customerWishlistBlock = $this->page->getLayout()->getBlock('customer.wishlist'); + + return $customerWishlistBlock->getChildBlock('wishlist_item_pager')->toHtml(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Block/LinkTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Block/LinkTest.php new file mode 100644 index 0000000000000..b7f124f7c1f6d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Block/LinkTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Wishlist\Block; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Class test link my wish list in customer menu. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + * @magentoAppIsolation disabled + */ +class LinkTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Link */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Link::class); + } + + /** + * @return void + */ + public function testWishListLinkVisible(): void + { + $this->assertContains('My Wish List', strip_tags($this->block->toHtml())); + } + + /** + * @magentoConfigFixture current_store wishlist/general/active 0 + * + * @return void + */ + public function testWishListLinkNotVisible(): void + { + $this->assertEmpty($this->block->toHtml()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three.php b/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three.php new file mode 100644 index 0000000000000..11752d5ba39f3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Wishlist\Model\WishlistFactory; +use Magento\Framework\Serialize\SerializerInterface; + +require __DIR__ . '/../../../Magento/Customer/_files/customer.php'; +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; + +$json = $objectManager->get(SerializerInterface::class); +$wishlistFactory = $objectManager->get(WishlistFactory::class); +$wishlist = $wishlistFactory->create(); +$wishlist->loadByCustomerId($customer->getId(), true); +$wishlist->addNewItem($product, $json->serialize(['qty' => 3])); diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three_rollback.php b/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three_rollback.php new file mode 100644 index 0000000000000..24bbccd5739f4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Wishlist/_files/wishlist_with_product_qty_three_rollback.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple_rollback.php'; +require __DIR__ . '/../../../Magento/Customer/_files/customer_rollback.php'; diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Newsletter/frontend/js/newsletter-sign-up.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Newsletter/frontend/js/newsletter-sign-up.test.js new file mode 100644 index 0000000000000..345a3fc47e7c3 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Newsletter/frontend/js/newsletter-sign-up.test.js @@ -0,0 +1,141 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'squire', + 'ko', + 'jquery', + 'mage/validation' +], function (Squire, ko, $) { + 'use strict'; + + var injector = new Squire(), + obj, + checkbox, + emailElem, + button, + response = ko.observable({}), + resolverMock = jasmine.createSpy('subscription-status-resolver', function (email, deferred) { + if (response().errors) { + deferred.reject(); + } else { + deferred.resolve(response().subscribed); + } + }).and.callThrough(), + mocks = { + 'Magento_Newsletter/js/subscription-status-resolver': resolverMock + }; + + beforeEach(function (done) { + checkbox = $('<input type="checkbox" class="checkbox" name="is_subscribed" id="is_subscribed"/>'); + emailElem = $('<input type="email" name="email" id="email_address"/>'); + button = $('<button type="submit" id="button"/>'); + $(document.body).append(checkbox).append(emailElem).append(button); + + injector.mock(mocks); + injector.require(['Magento_Newsletter/js/newsletter-sign-up'], function (Constr) { + obj = new Constr({ + submitButton: '#button', + signUpElement: '#is_subscribed' + }, '#email_address'); + done(); + }); + }); + + afterEach(function () { + try { + injector.clean(); + injector.remove(); + } catch (e) {} + + checkbox.remove(); + emailElem.remove(); + button.remove(); + }); + + describe('Magento_Newsletter/js/newsletter-sign-up', function () { + it('Check for properties defined', function () { + expect(obj.hasOwnProperty('submitButton')).toBeDefined(); + expect(typeof obj.submitButton).toEqual('string'); + expect(obj.hasOwnProperty('signUpElement')).toBeDefined(); + expect(typeof obj.signUpElement).toEqual('string'); + expect(obj.hasOwnProperty('element')).toBeDefined(); + expect(typeof obj.element).toEqual('string'); + }); + + it('Check sign-up process when Subscription is checked', function () { + emailElem.val('email@example.com'); + checkbox.prop('checked', true); + + obj.updateSignUpStatus(); + + expect(resolverMock).not.toHaveBeenCalled(); + expect(button.is(':disabled')).toBeFalsy(); + expect(checkbox.is(':checked')).toBeTruthy(); + }); + + it('Check sign-up process without email', function () { + checkbox.prop('checked', false); + + obj.updateSignUpStatus(); + + expect(resolverMock).not.toHaveBeenCalled(); + expect(checkbox.is(':checked')).toBeFalsy(); + }); + + it('Check sign-up process with incorrect email', function () { + emailElem.val('emailexample.com'); + checkbox.prop('checked', false); + + obj.updateSignUpStatus(); + + expect(resolverMock).not.toHaveBeenCalled(); + expect(checkbox.is(':checked')).toBeFalsy(); + }); + + it('Check Subscription with correct data', function () { + response({ + subscribed: true, + errors: false + }); + emailElem.val('email@example.com'); + checkbox.prop('checked', false); + + obj.updateSignUpStatus(); + + expect(resolverMock).toHaveBeenCalled(); + expect(checkbox.is(':checked')).toBeTruthy(); + expect(button.is(':disabled')).toBeFalsy(); + }); + + it('Check sign-up process with non-subscribed email', function () { + response({ + subscribed: false, + errors: false + }); + emailElem.val('email@example.com'); + checkbox.prop('checked', false); + + obj.updateSignUpStatus(); + + expect(resolverMock).toHaveBeenCalled(); + expect(checkbox.is(':checked')).toBeFalsy(); + }); + + it('Check sign-up process with errors', function () { + response({ + subscribed: true, + errors: true + }); + emailElem.val('email@example.com'); + checkbox.prop('checked', false); + + obj.updateSignUpStatus(); + + expect(resolverMock).toHaveBeenCalled(); + expect(checkbox.is(':checked')).toBeFalsy(); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js index b5c6e75248bfa..77ce2fb25f688 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/columns/image-preview.test.js @@ -13,10 +13,26 @@ define([ describe('Ui/js/grid/columns/image-preview', function () { var record = { - _rowIndex: 1, - rowNumber: 1 - }, - imagePreview; + _rowIndex: 1, + rowNumber: 1 + }, + imagePreview, + recordMock = { + _rowIndex: 2 + }, + secondRecordMock = { + _rowIndex: 1, + rowNumber: 1 + }, + elementMock = { + keyCode: 37 + }, + masonryMock = { + shows: jasmine.createSpy().and.returnValue([]), + rows: jasmine.createSpy().and.returnValue({ + 1: secondRecordMock + }) + }; beforeEach(function () { imagePreview = new Preview(); @@ -46,5 +62,36 @@ define([ }); }); + + describe('handleKeyDown method', function () { + + it('verify record changed on key down', function () { + var imageMock = document.createElement('img'), + originMock = $.fn.get; + + spyOn($.fn, 'get').and.returnValue(imageMock); + imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(2); + imagePreview.displayedRecord = ko.observable(); + imagePreview.displayedRecord(recordMock); + imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); + imagePreview.handleKeyDown(elementMock); + expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + + $.fn.get = originMock; + }); + + it('verify record not changed on key down when active element input', function () { + var input = $('<input id=\'input-fixture\'/>'); + + $(document.body).append(input); + input.focus(); + imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(1); + imagePreview.displayedRecord = ko.observable(1); + imagePreview.handleKeyDown(elementMock); + expect(imagePreview.displayedRecord()).toBe(1); + + $('#input-fixture').remove(); + }); + }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js index 5f8bfc2c98cc2..b53f49bd6103d 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js @@ -6,63 +6,190 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ define([ - 'mageUtils', + 'jquery', 'Magento_Ui/js/grid/data-storage' -], function (utils, DataStorage) { +], function ($, DataStorage) { 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { - describe('costructor', function () { - it('converts dataScope property to array', function () { + + describe('"initConfig" method', function () { + + it('returns self', function () { var model = new DataStorage({ dataScope: 'magento' }); - expect(model.dataScope).toEqual(['magento']); + expect(model.initConfig()).toEqual(model); }); - }); - describe('hasScopeChanged', function () { - it('is function', function () { + it('changes string dataScope property to an array', function () { var model = new DataStorage({ - dataScope: '' + dataScope: 'magento' }); - expect(model.hasScopeChanged).toBeDefined(); - expect(typeof model.hasScopeChanged).toEqual('function'); + expect(model.dataScope).toEqual(['magento']); }); - it('returns false if no requests have been made', function () { + it('changes empty string dataScope property to an empty array', function () { var model = new DataStorage({ dataScope: '' }); - expect(model.hasScopeChanged()).toBeFalsy(); + expect(model.dataScope).toEqual([]); }); - it('tells whether parameters defined in the dataScope property have changed', function () { - var params, newParams, model; + it('doesn\'t change non-string dataScope property', function () { + var testScope = { + testKey: 'test value' + }, + model = new DataStorage({ + dataScope: testScope + }); - params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 + expect(model.dataScope).toEqual(testScope); + }); + + it('initializes _requests property as an empty array', function () { + var model = new DataStorage(); + + model._requests = null; + model.initConfig(); + expect(model._requests).toEqual([]); + }); + }); + + describe('"getByIds" method', function () { + + it('returns false if data for ids is missing', function () { + var model = new DataStorage(); + + expect(model.getByIds([1,2,3])).toEqual(false); + }); + + it('returns array of items', function () { + var item = { + id_field_name: 'entity_id', + entity_id: '1' }, - sorting: {}, - paging: {} - }; + model = new DataStorage({ + data: { + 1: item + } + }); - newParams = utils.extend({}, params, { - search: 'magento', - filters: { - store_id: 1 - } - }); + expect(model.getByIds([1])).toEqual([item]); + }); - model = new DataStorage({ - dataScope: 'filters.store_id' - }); + }); + + describe('"getIds" method', function () { + + it('returns an array of entity_id\'s from provided data', function () { + var model = new DataStorage(), + ids = [ + { + id_field_name: 'entity_id', + entity_id: '1' + }, + { + id_field_name: 'entity_id', + entity_id: '54' + } + ]; + + expect(model.getIds(ids)).toEqual(['1', '54']); + }); + + it('returns an array of entity_id\'s from stored data if no arguments provided', function () { + var model = new DataStorage({ + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1' + }, + 2: { + id_field_name: 'entity_id', + entity_id: '42' + } + } + }); + + expect(model.getIds()).toEqual(['1', '42']); + }); + + }); + + describe('"getData" method', function () { + + var model = new DataStorage(); + + it('returns the result of requestData method if scope have been changed', function () { + var requestDataResult = 'requestDataResult'; + + spyOn(model, 'clearRequests'); + spyOn(model, 'hasScopeChanged').and.returnValue(true); + spyOn(model, 'requestData').and.returnValue(requestDataResult); + spyOn(model, 'getRequest'); + expect(model.getData()).toEqual(requestDataResult); + expect(model.clearRequests).toHaveBeenCalled(); + expect(model.getRequest).not.toHaveBeenCalled(); + }); + + it('returns the cached result if scope have not been changed', function () { + var cachedRequestDataResult = 'cachedRequestDataResult'; + + spyOn(model, 'clearRequests'); + spyOn(model, 'requestData'); + spyOn(model, 'hasScopeChanged').and.returnValue(false); + spyOn(model, 'getRequest').and.returnValue(true); + spyOn(model, 'getRequestData').and.returnValue(cachedRequestDataResult); + + expect(model.getData()).toEqual(cachedRequestDataResult); + expect(model.clearRequests).not.toHaveBeenCalled(); + expect(model.requestData).not.toHaveBeenCalled(); + }); + + it('returns the result of requestData method if refresh option is provided', function () { + var requestDataResult = 'requestDataResult', + options = { + refresh: true + }; + + spyOn(model, 'getRequest').and.returnValue(true); + spyOn(model, 'clearRequests'); + spyOn(model, 'hasScopeChanged').and.returnValue(true); + spyOn(model, 'requestData').and.returnValue(requestDataResult); + expect(model.getData({}, options)).toEqual(requestDataResult); + expect(model.clearRequests).toHaveBeenCalled(); + }); + + }); + + describe('"hasScopeChanged" method', function () { + + it('returns false if no requests have been made', function () { + var model = new DataStorage(); + + expect(model.hasScopeChanged()).toBeFalsy(); + }); + + it('returns true for not cached params', function () { + var params = { + search: '1', + filters: { + store_id: 0 + } + }, + newParams = { + search: '2', + filters: { + store_id: 1 + } + }, + model = new DataStorage({ + dataScope: 'filters.store_id' + }); model.cacheRequest({ totalRecords: 0 @@ -72,5 +199,303 @@ define([ expect(model.hasScopeChanged(newParams)).toBeTruthy(); }); }); + + describe('"updateData" method', function () { + var model = new DataStorage({ + dataScope: 'magento', + requestConfig: { + url: 'magento.com', + method: 'GET', + dataType: 'json' + }, + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1', + field: 'value' + } + } + }); + + it('updates data items', function () { + var data = [{ + id_field_name: 'entity_id', + entity_id: '1', + field: 'updatedValue' + }]; + + expect(model.updateData(data)).toEqual(model); + expect(model.getByIds([1])).toEqual(data); + }); + }); + + describe('"requestData" method', function () { + var model = new DataStorage(); + + it('Check Ajax request', function () { + var result = 'result'; + + spyOn(model, 'onRequestComplete').and.returnValue(result); + spyOn($, 'ajax').and.returnValue({ + /** + * Success result for ajax request + * + * @param {Function} handler + * @returns {*} + */ + done: function (handler) { + return handler(); + } + }); + expect(model.requestData({})).toEqual(result); + }); + }); + + describe('"getRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('returns cached request', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1'], + params: params, + totalRecords: 1, + errorMessage: '' + }; + + model._requests.push(request); + expect(model.getRequest(params)).toEqual(request); + }); + }); + + describe('"getRequestData" method', function () { + it('returns request data', function () { + var request = { + ids: [1,2], + totalRecords: 2, + errorMessage: '' + }, + items = [ + { + id_field_name: 'entity_id', + entity_id: '1' + }, + { + id_field_name: 'entity_id', + entity_id: '2' + } + ], + result = { + items: items, + totalRecords: 2, + errorMessage: '' + }, + model = new DataStorage({ + cachedRequestDelay: 0 + }); + + spyOn(model, 'getByIds').and.returnValue(items); + model.getRequestData(request).then(function (promiseResult) { + expect(promiseResult).toEqual(result); + }); + }); + }); + + describe('"cacheRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('adds the request to the cache', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + ids = ['1','2','3'], + data = { + items: ids, + totalRecords: 3, + errorMessage: '' + }, + request = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: '' + }; + + spyOn(model, 'removeRequest'); + spyOn(model, 'getIds').and.returnValue(ids); + model.cacheRequest(data, params); + expect(model.getRequest(params)).toEqual(request); + expect(model.removeRequest).not.toHaveBeenCalled(); + }); + + it('overwrites the previously cached request for the same params', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + ids = ['1','2','3'], + firstData = { + items: ids, + totalRecords: 3, + errorMessage: '' + }, + secondData = { + items: ids, + totalRecords: 3, + errorMessage: 'Error message' + }, + firstRequest = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: '' + }, + secondRequest = { + ids: ids, + params: params, + totalRecords: 3, + errorMessage: 'Error message' + }; + + spyOn(model, 'getIds').and.returnValue(ids); + model.cacheRequest(firstData, params); + expect(model.getRequest(params)).toEqual(firstRequest); + model.cacheRequest(secondData, params); + expect(model.getRequest(params)).toEqual(secondRequest); + }); + }); + + describe('"clearRequests" method', function () { + + it('removes all cached requests', function () { + var model = new DataStorage(), + params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }; + + model._requests.push({ + ids: ['1','2','3','4'], + params: params, + totalRecords: 4, + errorMessage: 'errorMessage' + }); + model.clearRequests(); + expect(model._requests).toEqual([]); + }); + }); + + describe('"removeRequest" method', function () { + + var model = new DataStorage(); + + it('removes the request from the cache', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1','2','3'], + params: params, + totalRecords: 3, + errorMessage: '' + }; + + model._requests = [request]; + expect(model.getRequest(params)).toEqual(request); + model.removeRequest(request); + expect(model.getRequest(params)).toBeFalsy(); + }); + }); + + describe('"wasRequested" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('returns false if request is not present in cache', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + expect(model.wasRequested(params)).toBeFalsy(); + }); + + it('returns true if request is present in cache', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1','2','3'], + params: params, + totalRecords: 3, + errorMessage: '' + }; + + model._requests = [request]; + + expect(model.wasRequested(params)).toBeTruthy(); + }); + }); + + describe('"onRequestComplete" method', function () { + + it('updates data and does not cache the request if caching is disabled', function () { + var model = new DataStorage({ + cacheRequests: false + }), + data = { + items: [] + }, + params = {}; + + spyOn(model, 'updateData'); + spyOn(model, 'cacheRequest'); + model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); + expect(model.cacheRequest).not.toHaveBeenCalled(); + }); + + it('updates data and adds the request to cache if caching is enabled', function () { + var model = new DataStorage({ + cacheRequests: true + }), + data = { + items: [] + }, + params = {}; + + spyOn(model, 'updateData'); + spyOn(model, 'cacheRequest'); + model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); + expect(model.cacheRequest).toHaveBeenCalled(); + }); + }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js index 8b00ecd3a2aed..3625d0898e942 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/modal/modal.test.js @@ -10,18 +10,45 @@ define([ 'use strict'; describe('ui/js/modal/modal', function () { - var element = $('<div>some element</div>'), + + var element, + modal; + + beforeEach(function () { + element = $('<div id="element">Element</div>'); modal = element.modal({}).data('mage-modal'); + $(element).append('<h1 class="modal-title"' + + ' data-role="title">Title</h1>' + + '<span class="modal-subtitle"' + + ' data-role="subTitle"></span>'); + }); + + afterEach(function () { + $('.modal-title').remove(); + $('#element').remove(); + + }); + it('Check for modal definition', function () { expect(modal).toBeDefined(); }); + it('Show/hide function check', function () { expect(element.trigger('openModal')).toBe(element); expect(element.trigger('closeModal')).toBe(element); }); + it('Integration: modal created on page', function () { expect($(modal).length).toEqual(1); }); + + it('Verify set title', function () { + var newTitle = 'New modal title'; + + modal.setTitle(newTitle); + expect($(modal.options.modalTitle).text()).toContain(newTitle); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); + }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/frontend/js/model/messages.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/frontend/js/model/messages.test.js new file mode 100644 index 0000000000000..54134c5b3166c --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/frontend/js/model/messages.test.js @@ -0,0 +1,109 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'uiRegistry', + 'Magento_Ui/js/model/messages' +], function (registry, Constr) { + 'use strict'; + + describe('Magento_Ui/js/model/messages', function () { + + var obj, + errorMessageText, + successMessageText, + messageObj; + + beforeEach(function () { + obj = new Constr( + { + provider: 'provName', + name: '', + index: '' + }); + errorMessageText = 'Error message test'; + successMessageText = 'Success message test'; + + registry.set('provName', { + /** Stub */ + on: function () { + }, + + /** Stub */ + get: function () { + }, + + /** Stub */ + set: function () { + } + }); + }); + + it('adds massage without parameters', function () { + var type = []; + + messageObj = { + message: 'Message test' + }; + expect(obj.add(messageObj, type)).toEqual(true); + expect(type).toEqual([messageObj.message]); + }); + + it('add message with parameters', function () { + var returnedObj, + type = []; + + messageObj = { + message: 'Message test case %1, case %2 and case %3', + parameters: [ + 'one', + 'two', + 'three' + ] + }; + returnedObj = ['Message test case ' + messageObj.parameters[0] + ', case ' + + messageObj.parameters[1] + ' and case ' + messageObj.parameters[2]]; + + expect(obj.add(messageObj, type)).toEqual(true); + expect(type).toEqual(returnedObj); + }); + + it('add error message, get error message, verify has error message', function () { + messageObj = { + message: errorMessageText + }; + + expect(obj.hasMessages()).toEqual(false); + expect(obj.addErrorMessage(messageObj)).toEqual(true); + expect(obj.getErrorMessages()()).toEqual([errorMessageText]); + expect(obj.hasMessages()).toEqual(true); + }); + + it('add success message, get success message, verify has success message', function () { + messageObj = { + message: successMessageText + }; + + expect(obj.addSuccessMessage(messageObj)).toEqual(true); + expect(obj.getSuccessMessages()()).toEqual([successMessageText]); + expect(obj.hasMessages()).toEqual(true); + }); + + it('cleaning messages', function () { + messageObj = { + message: 'Message test case %1, case %2 and case %3', + parameters: [ + 'one', + 'two', + 'three' + ] + }; + expect(obj.addErrorMessage(messageObj)).toEqual(true); + obj.clear(); + expect(obj.getErrorMessages()()).toEqual([]); + expect(obj.hasMessages()).toEqual(false); + }); + }); +}); diff --git a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php index 20442f9388235..cd4c8689ea004 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php +++ b/dev/tests/static/framework/Magento/Sniffs/Annotation/AnnotationFormatValidator.php @@ -94,7 +94,7 @@ private function validateSpacingBetweenShortAndLongDescriptions( && $tokens[$shortPtr]['line'] + 1 === $tokens[$shortPtrEnd]['line'] && $tokens[$shortPtrEnd]['code'] !== T_DOC_COMMENT_TAG ) { - $error = 'There must be exactly one blank line between lines'; + $error = 'There must be exactly one blank line between lines short and long descriptions'; $phpcsFile->addFixableError($error, $shortPtrEnd + 1, 'MethodAnnotation'); } if ($shortPtrEnd != $shortPtr) { diff --git a/dev/tests/static/framework/Magento/TestFramework/Inspection/AbstractCommand.php b/dev/tests/static/framework/Magento/TestFramework/Inspection/AbstractCommand.php index 9ce9570b53ffb..f917559fa1bf9 100644 --- a/dev/tests/static/framework/Magento/TestFramework/Inspection/AbstractCommand.php +++ b/dev/tests/static/framework/Magento/TestFramework/Inspection/AbstractCommand.php @@ -9,6 +9,9 @@ */ namespace Magento\TestFramework\Inspection; +/** + * Abstract class for commands + */ abstract class AbstractCommand { /** @@ -47,6 +50,7 @@ public function __construct($reportFile) * @param array $whiteList Files/directories to be inspected * @param array $blackList Files/directories to be excluded from the inspection * @return bool + * phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod */ public function run(array $whiteList, array $blackList = []) { @@ -118,7 +122,9 @@ abstract protected function _buildShellCmd($whiteList, $blackList); protected function _execShellCmd($shellCmd) { $output = []; + //phpcs:disable exec($shellCmd . ' 2>&1', $output, $this->_lastExitCode); + //phpcs:enable $this->_lastOutput = implode(PHP_EOL, $output); return $this->_lastExitCode === 0 ? $this->_lastOutput : false; } diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Annotation/_files/class_annotation_nospacingbetweenLines_errors.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Annotation/_files/class_annotation_nospacingbetweenLines_errors.txt index 01c145ad6c29f..0102ca7f79a1f 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Annotation/_files/class_annotation_nospacingbetweenLines_errors.txt +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Annotation/_files/class_annotation_nospacingbetweenLines_errors.txt @@ -3,10 +3,10 @@ FILE: ...tation/_fixtures/ClassAnnotationNoSpacingBetweenLinesFixture.php\n ----------------------------------------------------------------------\n FOUND 1 ERROR AFFECTING 1 LINE\n ----------------------------------------------------------------------\n - 13 | ERROR | [x] There must be exactly one blank line between lines\n + 13 | ERROR | [x] There must be exactly one blank line between lines short and long descriptions\n ----------------------------------------------------------------------\n PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY\n ----------------------------------------------------------------------\n \n \n -' \ No newline at end of file +' diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php index fa0d365061858..60855043a8c4e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php @@ -154,6 +154,13 @@ class DependencyTest extends \PHPUnit\Framework\TestCase */ private static $routesWhitelist = null; + /** + * Redundant dependencies whitelist + * + * @var array|null + */ + private static $redundantDependenciesWhitelist = null; + /** * @var RouteMapper */ @@ -185,6 +192,7 @@ public static function setUpBeforeClass() self::_prepareMapLayoutHandles(); self::getLibraryWhiteLists(); + self::getRedundantDependenciesWhiteLists(); self::_initDependencies(); self::_initThemes(); @@ -206,6 +214,26 @@ private static function getLibraryWhiteLists() } } + /** + * Initialize redundant dependencies whitelist + * + * @return array + */ + private static function getRedundantDependenciesWhiteLists(): array + { + if (is_null(self::$redundantDependenciesWhitelist)) { + $redundantDependenciesWhitelistFilePattern = + realpath(__DIR__) . '/_files/dependency_test/whitelist/redundant_dependencies_*.php'; + $redundantDependenciesWhitelist = []; + foreach (glob($redundantDependenciesWhitelistFilePattern) as $fileName) { + //phpcs:ignore Magento2.Performance.ForeachArrayMerge + $redundantDependenciesWhitelist = array_merge($redundantDependenciesWhitelist, include $fileName); + } + self::$redundantDependenciesWhitelist = $redundantDependenciesWhitelist; + } + return self::$redundantDependenciesWhitelist; + } + /** * Initialize default themes */ @@ -532,6 +560,9 @@ public function testRedundant() foreach (array_keys(self::$mapDependencies) as $module) { $result = []; $redundant = $this->_getDependencies($module, self::TYPE_HARD, self::MAP_TYPE_REDUNDANT); + if (isset(self::$redundantDependenciesWhitelist[$module])) { + $redundant = array_diff($redundant, self::$redundantDependenciesWhitelist[$module]); + } if (!empty($redundant)) { $result[] = sprintf( "\r\nModule %s: %s [%s]", diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/autogenerated_class_not_in_constructor_whitelist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/autogenerated_class_not_in_constructor_whitelist.php index ba8f7e3dd1420..f8979ef6ab15e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/autogenerated_class_not_in_constructor_whitelist.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/autogenerated_class_not_in_constructor_whitelist.php @@ -9,5 +9,6 @@ 'Symfony\Component\Console\Application', 'Customer\Address\Attributes', 'Order\Address\Type', - 'Order\Address\Attributes' + 'Order\Address\Attributes', + 'This\Is\Another\Ns', ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php index 242e4ebb22a54..48eb64ffea27e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/copyright/blacklist.php @@ -10,4 +10,5 @@ '/setup\/src\/Zend\/Mvc\/Controller\/LazyControllerAbstractFactory\.php/', '/app\/code\/(?!Magento)[^\/]*/', '#dev/tests/setup-integration/testsuite/Magento/Developer/_files/\S*\.xml$#', + '/lib\/internal\/Magento\/Framework\/File\/Test\/Unit\/_files\/blank.html$/' ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php index 8ccda77a25191..b7717492fd124 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php @@ -142,7 +142,7 @@ private static function getAddedFilesList($changedFilesBaseDir) function () { // if no list files, probably, this is the dev environment // phpcs:ignore Generic.PHP.NoSilencedErrors,Magento2.Security.InsecureFunction - @exec('git diff --cached --name-only', $addedFiles); + @exec('git diff --cached --name-only --diff-filter=A', $addedFiles); return $addedFiles; } ); diff --git a/lib/internal/Magento/Framework/File/Mime.php b/lib/internal/Magento/Framework/File/Mime.php index ed370b1beae54..148f43d47cfd4 100644 --- a/lib/internal/Magento/Framework/File/Mime.php +++ b/lib/internal/Magento/Framework/File/Mime.php @@ -78,6 +78,18 @@ class Mime 'svg' => 'image/svg+xml', ]; + /** + * List of generic MIME types + * + * The file mime type should be detected by the file's extension if the native mime type is one of the listed below. + * + * @var array + */ + private $genericMimeTypes = [ + 'application/x-empty', + 'inode/x-empty', + ]; + /** * Get mime type of a file * @@ -120,7 +132,11 @@ private function getNativeMimeType(string $file): string $extension = $this->getFileExtension($file); $result = mime_content_type($file); if (isset($this->mimeTypes[$extension], $this->defineByExtensionList[$extension]) - && (strpos($result, 'text/') === 0 || strpos($result, 'image/svg') === 0) + && ( + strpos($result, 'text/') === 0 + || strpos($result, 'image/svg') === 0 + || in_array($result, $this->genericMimeTypes, true) + ) ) { $result = $this->mimeTypes[$extension]; } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php index 1a964c141dd34..0ae1542a2c0e1 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\File\Test\Unit; +/** + * Test mime type utility for correct + */ class MimeTest extends \PHPUnit\Framework\TestCase { /** @@ -12,6 +15,9 @@ class MimeTest extends \PHPUnit\Framework\TestCase */ private $object; + /** + * @inheritDoc + */ protected function setUp() { $this->object = new \Magento\Framework\File\Mime(); @@ -42,12 +48,13 @@ public function testGetMimeType($file, $expectedType) /** * @return array */ - public function getMimeTypeDataProvider() + public function getMimeTypeDataProvider(): array { return [ 'javascript' => [__DIR__ . '/_files/javascript.js', 'application/javascript'], 'weird extension' => [__DIR__ . '/_files/file.weird', 'application/octet-stream'], 'weird uppercase extension' => [__DIR__ . '/_files/UPPERCASE.WEIRD', 'application/octet-stream'], + 'generic mime type' => [__DIR__ . '/_files/blank.html', 'text/html'], ]; } } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/_files/blank.html b/lib/internal/Magento/Framework/File/Test/Unit/_files/blank.html new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php index f23ed87971a39..484eed347be0f 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php @@ -67,8 +67,8 @@ protected function assertWritable($path) */ protected function assertIsFile($path) { - clearstatcache(); $absolutePath = $this->driver->getAbsolutePath($this->path, $path); + clearstatcache(true, $absolutePath); if (!$this->driver->isFile($absolutePath)) { throw new FileSystemException( new \Magento\Framework\Phrase('The "%1" file doesn\'t exist.', [$absolutePath]) diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 59c9775d73a0a..27df19f66c7aa 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -11,11 +11,13 @@ use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\Filesystem\Glob; +use Magento\Framework\Phrase; /** - * Class File + * Filesystem driver that uses the local filesystem. + * + * Assumed that stat cache is cleanup before test filesystem * - * @package Magento\Framework\Filesystem\Driver * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class File implements DriverInterface @@ -48,11 +50,12 @@ protected function getWarningMessage() */ public function isExists($path) { - clearstatcache(); - $result = @file_exists($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @file_exists($filename); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -67,11 +70,12 @@ public function isExists($path) */ public function stat($path) { - clearstatcache(); - $result = @stat($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @stat($filename); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase('Cannot gather stats! %1', [$this->getWarningMessage()]) + new Phrase('Cannot gather stats! %1', [$this->getWarningMessage()]) ); } return $result; @@ -86,11 +90,12 @@ public function stat($path) */ public function isReadable($path) { - clearstatcache(); - $result = @is_readable($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @is_readable($filename); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -105,11 +110,12 @@ public function isReadable($path) */ public function isFile($path) { - clearstatcache(); - $result = @is_file($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @is_file($filename); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -124,11 +130,12 @@ public function isFile($path) */ public function isDirectory($path) { - clearstatcache(); - $result = @is_dir($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @is_dir($filename); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -145,11 +152,12 @@ public function isDirectory($path) */ public function fileGetContents($path, $flag = null, $context = null) { - clearstatcache(); - $result = @file_get_contents($this->getScheme() . $path, $flag, $context); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @file_get_contents($filename, $flag, $context); if (false === $result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The contents from the "%1" file can\'t be read. %2', [$path, $this->getWarningMessage()] ) @@ -167,11 +175,12 @@ public function fileGetContents($path, $flag = null, $context = null) */ public function isWritable($path) { - clearstatcache(); - $result = @is_writable($this->getScheme() . $path); + $filename = $this->getScheme() . $path; + clearstatcache(false, $filename); + $result = @is_writable($filename); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -225,7 +234,7 @@ private function mkdirRecursive($path, $permissions = 0777) $result = true; } else { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'Directory "%1" cannot be created %2', [$path, $this->getWarningMessage()] ) @@ -255,7 +264,7 @@ public function readDirectory($path) sort($result); return $result; } catch (\Exception $e) { - throw new FileSystemException(new \Magento\Framework\Phrase($e->getMessage()), $e); + throw new FileSystemException(new Phrase($e->getMessage()), $e); } } @@ -298,7 +307,7 @@ public function rename($oldPath, $newPath, DriverInterface $targetDriver = null) } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The path "%1" cannot be renamed into "%2" %3', [$oldPath, $newPath, $this->getWarningMessage()] ) @@ -327,7 +336,7 @@ public function copy($source, $destination, DriverInterface $targetDriver = null } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The file or directory "%1" cannot be copied to "%2" %3', [ $source, @@ -357,7 +366,7 @@ public function symlink($source, $destination, DriverInterface $targetDriver = n } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'A symlink for "%1" can\'t be created and placed to "%2". %3', [ $source, @@ -382,7 +391,7 @@ public function deleteFile($path) $result = @unlink($this->getScheme() . $path); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The "%1" file can\'t be deleted. %2', [$path, $this->getWarningMessage()] ) @@ -418,7 +427,7 @@ public function deleteDirectory($path) if (!empty($exceptionMessages)) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( \implode(' ', $exceptionMessages) ) ); @@ -432,7 +441,7 @@ public function deleteDirectory($path) } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The directory "%1" cannot be deleted %2', [$path, $this->getWarningMessage()] ) @@ -454,7 +463,7 @@ public function changePermissions($path, $permissions) $result = @chmod($this->getScheme() . $path, $permissions); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) @@ -482,7 +491,7 @@ public function changePermissionsRecursively($path, $dirPermissions, $filePermis } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) @@ -504,7 +513,7 @@ public function changePermissionsRecursively($path, $dirPermissions, $filePermis } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The permissions can\'t be changed for the "%1" path. %2.', [$path, $this->getWarningMessage()] ) @@ -531,7 +540,7 @@ public function touch($path, $modificationTime = null) } if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The "%1" file or directory can\'t be touched. %2', [$path, $this->getWarningMessage()] ) @@ -552,9 +561,9 @@ public function touch($path, $modificationTime = null) public function filePutContents($path, $content, $mode = null) { $result = @file_put_contents($this->getScheme() . $path, $content, $mode); - if (!$result) { + if ($result === false) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The specified "%1" file couldn\'t be written. %2', [$path, $this->getWarningMessage()] ) @@ -576,7 +585,7 @@ public function fileOpen($path, $mode) $result = @fopen($this->getScheme() . $path, $mode); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase('File "%1" cannot be opened %2', [$path, $this->getWarningMessage()]) + new Phrase('File "%1" cannot be opened %2', [$path, $this->getWarningMessage()]) ); } return $result; @@ -593,12 +602,15 @@ public function fileOpen($path, $mode) */ public function fileReadLine($resource, $length, $ending = null) { + // phpcs:disable $result = @stream_get_line($resource, $length, $ending); + // phpcs:enable if (false === $result) { throw new FileSystemException( - new \Magento\Framework\Phrase('File cannot be read %1', [$this->getWarningMessage()]) + new Phrase('File cannot be read %1', [$this->getWarningMessage()]) ); } + return $result; } @@ -615,7 +627,7 @@ public function fileRead($resource, $length) $result = @fread($resource, $length); if ($result === false) { throw new FileSystemException( - new \Magento\Framework\Phrase('File cannot be read %1', [$this->getWarningMessage()]) + new Phrase('File cannot be read %1', [$this->getWarningMessage()]) ); } return $result; @@ -637,7 +649,7 @@ public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'The "%1" CSV handle is incorrect. Verify the handle and try again.', [$this->getWarningMessage()] ) @@ -658,7 +670,7 @@ public function fileTell($resource) $result = @ftell($resource); if ($result === null) { throw new FileSystemException( - new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) ); } return $result; @@ -678,7 +690,7 @@ public function fileSeek($resource, $offset, $whence = SEEK_SET) $result = @fseek($resource, $offset, $whence); if ($result === -1) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" fileSeek execution.', [$this->getWarningMessage()] ) @@ -710,7 +722,7 @@ public function fileClose($resource) $result = @fclose($resource); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" fileClose execution.', [$this->getWarningMessage()] ) @@ -756,7 +768,7 @@ public function fileWrite($resource, $data) */ private function fileSystemException($message, $arguments = []) { - throw new FileSystemException(new \Magento\Framework\Phrase($message, $arguments)); + throw new FileSystemException(new Phrase($message, $arguments)); } /** @@ -775,7 +787,7 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure * Security enhancement for CSV data processing by Excel-like applications. * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 * - * @var $value string|\Magento\Framework\Phrase + * @var $value string|Phrase */ foreach ($data as $key => $value) { if (!is_string($value)) { @@ -789,7 +801,7 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure $result = @fputcsv($resource, $data, $delimiter, $enclosure); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" filePutCsv execution.', [$this->getWarningMessage()] ) @@ -810,7 +822,7 @@ public function fileFlush($resource) $result = @fflush($resource); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" fileFlush execution.', [$this->getWarningMessage()] ) @@ -832,7 +844,7 @@ public function fileLock($resource, $lockMode = LOCK_EX) $result = @flock($resource, $lockMode); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" fileLock execution.', [$this->getWarningMessage()] ) @@ -853,7 +865,7 @@ public function fileUnlock($resource) $result = @flock($resource, LOCK_UN); if (!$result) { throw new FileSystemException( - new \Magento\Framework\Phrase( + new Phrase( 'An error occurred during "%1" fileUnlock execution.', [$this->getWarningMessage()] ) @@ -945,7 +957,7 @@ public function readDirectoryRecursively($path = null) $result[] = $file->getPathname(); } } catch (\Exception $e) { - throw new FileSystemException(new \Magento\Framework\Phrase($e->getMessage()), $e); + throw new FileSystemException(new Phrase($e->getMessage()), $e); } return $result; } @@ -976,7 +988,7 @@ public function getRealPathSafety($path) //Removing redundant directory separators. $path = preg_replace( - '/\\' .DIRECTORY_SEPARATOR .'\\' .DIRECTORY_SEPARATOR .'+/', + '/\\' . DIRECTORY_SEPARATOR . '\\' . DIRECTORY_SEPARATOR . '+/', DIRECTORY_SEPARATOR, $path ); diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php index f32624f4e7513..273425183577e 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php @@ -11,7 +11,7 @@ use Magento\Framework\Exception\FileSystemException; /** - * Class Http + * Allows interacting with http endpoint like with FileSystem */ class Http extends File { @@ -83,8 +83,9 @@ public function stat($path) */ public function fileGetContents($path, $flags = null, $context = null) { - clearstatcache(); - $result = @file_get_contents($this->getScheme() . $path, $flags, $context); + $fullPath = $this->getScheme() . $path; + clearstatcache(false, $fullPath); + $result = @file_get_contents($fullPath, $flags, $context); if (false === $result) { throw new FileSystemException( new \Magento\Framework\Phrase( @@ -109,7 +110,7 @@ public function fileGetContents($path, $flags = null, $context = null) public function filePutContents($path, $content, $mode = null, $context = null) { $result = @file_put_contents($this->getScheme() . $path, $content, $mode, $context); - if (!$result) { + if ($result === false) { throw new FileSystemException( new \Magento\Framework\Phrase( 'The specified "%1" file couldn\'t be written. %2', @@ -196,8 +197,13 @@ public function fileOpen($path, $mode) */ public function fileReadLine($resource, $length, $ending = null) { - $result = @stream_get_line($resource, $length, $ending); - + try { + $result = @stream_get_line($resource, $length, $ending); + } catch (\Exception $e) { + throw new FileSystemException( + new \Magento\Framework\Phrase('Stream get line failed %1', [$e->getMessage()]) + ); + } return $result; } diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php new file mode 100644 index 0000000000000..beeb1e928262c --- /dev/null +++ b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php @@ -0,0 +1,1007 @@ +<?php +/** + * Origin filesystem driver + * + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Filesystem\Driver; + +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Filesystem\DriverInterface; +use Magento\Framework\Filesystem\Glob; +use Magento\Framework\Phrase; + +/** + * Filesystem driver that uses the local filesystem. + * + * Assumed that stat cache is cleanup by data modification methods + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + */ +class StatefulFile implements DriverInterface +{ + /** + * @var string + */ + protected $scheme = ''; + + /** + * Returns last warning message string + * + * @return string + */ + protected function getWarningMessage() + { + $warning = error_get_last(); + if ($warning && $warning['type'] == E_WARNING) { + return 'Warning!' . $warning['message']; + } + return null; + } + + /** + * Is file or directory exist in file system + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function isExists($path) + { + $result = @file_exists($this->getScheme() . $path); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Gathers the statistics of the given path + * + * @param string $path + * @return array + * @throws FileSystemException + */ + public function stat($path) + { + $result = @stat($this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase('Cannot gather stats! %1', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Check permissions for reading file or directory + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function isReadable($path) + { + $result = @is_readable($this->getScheme() . $path); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Tells whether the filename is a regular file + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function isFile($path) + { + $result = @is_file($this->getScheme() . $path); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Tells whether the filename is a regular directory + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function isDirectory($path) + { + $result = @is_dir($this->getScheme() . $path); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Retrieve file contents from given path + * + * @param string $path + * @param string|null $flag + * @param resource|null $context + * @return string + * @throws FileSystemException + */ + public function fileGetContents($path, $flag = null, $context = null) + { + $result = @file_get_contents($this->getScheme() . $path, $flag, $context); + if (false === $result) { + throw new FileSystemException( + new Phrase( + 'The contents from the "%1" file can\'t be read. %2', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Check if given path is writable + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function isWritable($path) + { + $result = @is_writable($this->getScheme() . $path); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Returns parent directory's path + * + * @param string $path + * @return string + */ + public function getParentDirectory($path) + { + return dirname($this->getScheme() . $path); + } + + /** + * Create directory + * + * @param string $path + * @param int $permissions + * @return bool + * @throws FileSystemException + */ + public function createDirectory($path, $permissions = 0777) + { + clearstatcache(true, $path); + return $this->mkdirRecursive($path, $permissions); + } + + /** + * Create a directory recursively taking into account race conditions + * + * @param string $path + * @param int $permissions + * @return bool + * @throws FileSystemException + */ + private function mkdirRecursive($path, $permissions = 0777) + { + $path = $this->getScheme() . $path; + if (is_dir($path)) { + return true; + } + $parentDir = dirname($path); + while (!is_dir($parentDir)) { + $this->mkdirRecursive($parentDir, $permissions); + } + $result = @mkdir($path, $permissions); + clearstatcache(true, $path); + if (!$result) { + if (is_dir($path)) { + $result = true; + } else { + throw new FileSystemException( + new Phrase( + 'Directory "%1" cannot be created %2', + [$path, $this->getWarningMessage()] + ) + ); + } + } + return $result; + } + + /** + * Read directory + * + * @param string $path + * @return string[] + * @throws FileSystemException + */ + public function readDirectory($path) + { + try { + $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS; + $iterator = new \FilesystemIterator($path, $flags); + $result = []; + /** @var \FilesystemIterator $file */ + foreach ($iterator as $file) { + $result[] = $file->getPathname(); + } + sort($result); + return $result; + } catch (\Exception $e) { + throw new FileSystemException(new Phrase($e->getMessage()), $e); + } + } + + /** + * Search paths by given regex + * + * @param string $pattern + * @param string $path + * @return string[] + * @throws FileSystemException + */ + public function search($pattern, $path) + { + $globPattern = rtrim($path, '/') . '/' . ltrim($pattern, '/'); + $result = Glob::glob($globPattern, Glob::GLOB_BRACE); + return is_array($result) ? $result : []; + } + + /** + * Renames a file or directory + * + * @param string $oldPath + * @param string $newPath + * @param DriverInterface|null $targetDriver + * @return bool + * @throws FileSystemException + */ + public function rename($oldPath, $newPath, DriverInterface $targetDriver = null) + { + $result = false; + $targetDriver = $targetDriver ?: $this; + if (get_class($targetDriver) == get_class($this)) { + $result = @rename($this->getScheme() . $oldPath, $newPath); + clearstatcache(true, $this->getScheme() . $oldPath); + clearstatcache(true, $newPath); + } else { + $content = $this->fileGetContents($oldPath); + if (false !== $targetDriver->filePutContents($newPath, $content)) { + $result = $this->deleteFile($newPath); + } + } + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The path "%1" cannot be renamed into "%2" %3', + [$oldPath, $newPath, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Copy source into destination + * + * @param string $source + * @param string $destination + * @param DriverInterface|null $targetDriver + * @return bool + * @throws FileSystemException + */ + public function copy($source, $destination, DriverInterface $targetDriver = null) + { + $targetDriver = $targetDriver ?: $this; + if (get_class($targetDriver) == get_class($this)) { + $result = @copy($this->getScheme() . $source, $destination); + clearstatcache(true, $destination); + } else { + $content = $this->fileGetContents($source); + $result = $targetDriver->filePutContents($destination, $content); + } + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The file or directory "%1" cannot be copied to "%2" %3', + [ + $source, + $destination, + $this->getWarningMessage() + ] + ) + ); + } + return $result; + } + + /** + * Create symlink on source and place it into destination + * + * @param string $source + * @param string $destination + * @param DriverInterface|null $targetDriver + * @return bool + * @throws FileSystemException + */ + public function symlink($source, $destination, DriverInterface $targetDriver = null) + { + $result = false; + if ($targetDriver === null || get_class($targetDriver) == get_class($this)) { + $result = @symlink($this->getScheme() . $source, $destination); + clearstatcache(true, $destination); + } + if (!$result) { + throw new FileSystemException( + new Phrase( + 'A symlink for "%1" can\'t be created and placed to "%2". %3', + [ + $source, + $destination, + $this->getWarningMessage() + ] + ) + ); + } + return $result; + } + + /** + * Delete file + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function deleteFile($path) + { + $result = @unlink($this->getScheme() . $path); + clearstatcache(true, $this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The "%1" file can\'t be deleted. %2', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Recursive delete directory + * + * @param string $path + * @return bool + * @throws FileSystemException + */ + public function deleteDirectory($path) + { + $exceptionMessages = []; + $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS; + $iterator = new \FilesystemIterator($path, $flags); + /** @var \FilesystemIterator $entity */ + foreach ($iterator as $entity) { + try { + if ($entity->isDir()) { + $this->deleteDirectory($entity->getPathname()); + } else { + $this->deleteFile($entity->getPathname()); + } + } catch (FileSystemException $exception) { + $exceptionMessages[] = $exception->getMessage(); + } + } + + if (!empty($exceptionMessages)) { + throw new FileSystemException( + new Phrase( + \implode(' ', $exceptionMessages) + ) + ); + } + + $fullPath = $this->getScheme() . $path; + if (is_link($fullPath)) { + $result = @unlink($fullPath); + } else { + $result = @rmdir($fullPath); + } + clearstatcache(true, $fullPath); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The directory "%1" cannot be deleted %2', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Change permissions of given path + * + * @param string $path + * @param int $permissions + * @return bool + * @throws FileSystemException + */ + public function changePermissions($path, $permissions) + { + $result = @chmod($this->getScheme() . $path, $permissions); + clearstatcache(false, $this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The permissions can\'t be changed for the "%1" path. %2.', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Recursively change permissions of given path + * + * @param string $path + * @param int $dirPermissions + * @param int $filePermissions + * @return bool + * @throws FileSystemException + */ + public function changePermissionsRecursively($path, $dirPermissions, $filePermissions) + { + $result = true; + if ($this->isFile($path)) { + $result = @chmod($path, $filePermissions); + } else { + $result = @chmod($path, $dirPermissions); + } + clearstatcache(false, $this->getScheme() . $path); + + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The permissions can\'t be changed for the "%1" path. %2.', + [$path, $this->getWarningMessage()] + ) + ); + } + + $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS; + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path, $flags), + \RecursiveIteratorIterator::CHILD_FIRST + ); + /** @var \FilesystemIterator $entity */ + foreach ($iterator as $entity) { + if ($entity->isDir()) { + $result = @chmod($entity->getPathname(), $dirPermissions); + } else { + $result = @chmod($entity->getPathname(), $filePermissions); + } + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The permissions can\'t be changed for the "%1" path. %2.', + [$path, $this->getWarningMessage()] + ) + ); + } + } + return $result; + } + + /** + * Sets access and modification time of file. + * + * @param string $path + * @param int|null $modificationTime + * @return bool + * @throws FileSystemException + */ + public function touch($path, $modificationTime = null) + { + if (!$modificationTime) { + $result = @touch($this->getScheme() . $path); + } else { + $result = @touch($this->getScheme() . $path, $modificationTime); + } + clearstatcache(true, $this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The "%1" file or directory can\'t be touched. %2', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Write contents to file in given path + * + * @param string $path + * @param string $content + * @param string|null $mode + * @return int The number of bytes that were written. + * @throws FileSystemException + */ + public function filePutContents($path, $content, $mode = null) + { + $result = @file_put_contents($this->getScheme() . $path, $content, $mode); + clearstatcache(true, $this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'The specified "%1" file couldn\'t be written. %2', + [$path, $this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Open file + * + * @param string $path + * @param string $mode + * @return resource file + * @throws FileSystemException + */ + public function fileOpen($path, $mode) + { + $result = @fopen($this->getScheme() . $path, $mode); + clearstatcache(true, $this->getScheme() . $path); + if (!$result) { + throw new FileSystemException( + new Phrase('File "%1" cannot be opened %2', [$path, $this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Reads the line content from file pointer (with specified number of bytes from the current position). + * + * @param resource $resource + * @param int $length + * @param string $ending [optional] + * @return string + * @throws FileSystemException + */ + public function fileReadLine($resource, $length, $ending = null) + { + // phpcs:disable + $result = @stream_get_line($resource, $length, $ending); + // phpcs:enable + if (false === $result) { + throw new FileSystemException( + new Phrase('File cannot be read %1', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Reads the specified number of bytes from the current position. + * + * @param resource $resource + * @param int $length + * @return string + * @throws FileSystemException + */ + public function fileRead($resource, $length) + { + $result = @fread($resource, $length); + if ($result === false) { + throw new FileSystemException( + new Phrase('File cannot be read %1', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Reads one CSV row from the file + * + * @param resource $resource + * @param int $length [optional] + * @param string $delimiter [optional] + * @param string $enclosure [optional] + * @param string $escape [optional] + * @return array|bool|null + * @throws FileSystemException + */ + public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') + { + $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape); + if ($result === null) { + throw new FileSystemException( + new Phrase( + 'The "%1" CSV handle is incorrect. Verify the handle and try again.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Returns position of read/write pointer + * + * @param resource $resource + * @return int + * @throws FileSystemException + */ + public function fileTell($resource) + { + $result = @ftell($resource); + if ($result === null) { + throw new FileSystemException( + new Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()]) + ); + } + return $result; + } + + /** + * Seeks to the specified offset + * + * @param resource $resource + * @param int $offset + * @param int $whence + * @return int + * @throws FileSystemException + */ + public function fileSeek($resource, $offset, $whence = SEEK_SET) + { + $result = @fseek($resource, $offset, $whence); + if ($result === -1) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" fileSeek execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Returns true if pointer at the end of file or in case of exception + * + * @param resource $resource + * @return boolean + */ + public function endOfFile($resource) + { + return feof($resource); + } + + /** + * Close file + * + * @param resource $resource + * @return boolean + * @throws FileSystemException + */ + public function fileClose($resource) + { + $result = @fclose($resource); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" fileClose execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Writes data to file + * + * @param resource $resource + * @param string $data + * @return int + * @throws FileSystemException + */ + public function fileWrite($resource, $data) + { + $lenData = strlen($data); + for ($result = 0; $result < $lenData; $result += $fwrite) { + $fwrite = @fwrite($resource, substr($data, $result)); + if (0 === $fwrite) { + $this->fileSystemException('Unable to write'); + } + if (false === $fwrite) { + $this->fileSystemException( + 'An error occurred during "%1" fileWrite execution.', + [$this->getWarningMessage()] + ); + } + } + + return $result; + } + + /** + * Throw a FileSystemException with a Phrase of message and optional arguments + * + * @param string $message + * @param array $arguments + * @return void + * @throws FileSystemException + */ + private function fileSystemException($message, $arguments = []) + { + throw new FileSystemException(new Phrase($message, $arguments)); + } + + /** + * Writes one CSV row to the file. + * + * @param resource $resource + * @param array $data + * @param string $delimiter + * @param string $enclosure + * @return int + * @throws FileSystemException + */ + public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure = '"') + { + /** + * Security enhancement for CSV data processing by Excel-like applications. + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 + * + * @var $value string|Phrase + */ + foreach ($data as $key => $value) { + if (!is_string($value)) { + $value = (string)$value; + } + if (isset($value[0]) && in_array($value[0], ['=', '+', '-'])) { + $data[$key] = ' ' . $value; + } + } + + $result = @fputcsv($resource, $data, $delimiter, $enclosure); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" filePutCsv execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Flushes the output + * + * @param resource $resource + * @return bool + * @throws FileSystemException + */ + public function fileFlush($resource) + { + $result = @fflush($resource); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" fileFlush execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Lock file in selected mode + * + * @param resource $resource + * @param int $lockMode + * @return bool + * @throws FileSystemException + */ + public function fileLock($resource, $lockMode = LOCK_EX) + { + $result = @flock($resource, $lockMode); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" fileLock execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Unlock file + * + * @param resource $resource + * @return bool + * @throws FileSystemException + */ + public function fileUnlock($resource) + { + $result = @flock($resource, LOCK_UN); + if (!$result) { + throw new FileSystemException( + new Phrase( + 'An error occurred during "%1" fileUnlock execution.', + [$this->getWarningMessage()] + ) + ); + } + return $result; + } + + /** + * Returns an absolute path for the given one. + * + * @param string $basePath + * @param string $path + * @param string|null $scheme + * @return string + */ + public function getAbsolutePath($basePath, $path, $scheme = null) + { + // check if the path given is already an absolute path containing the + // basepath. so if the basepath starts at position 0 in the path, we + // must not concatinate them again because path is already absolute. + if (0 === strpos($path, $basePath)) { + return $this->getScheme($scheme) . $path; + } + + return $this->getScheme($scheme) . $basePath . ltrim($this->fixSeparator($path), '/'); + } + + /** + * Retrieves relative path + * + * @param string $basePath + * @param string $path + * @return string + */ + public function getRelativePath($basePath, $path = null) + { + $path = $this->fixSeparator($path); + if (strpos($path, $basePath) === 0 || $basePath == $path . '/') { + $result = substr($path, strlen($basePath)); + } else { + $result = $path; + } + return $result; + } + + /** + * Fixes path separator. + * + * Utility method. + * + * @param string $path + * @return string + */ + protected function fixSeparator($path) + { + return str_replace('\\', '/', $path); + } + + /** + * Return path with scheme + * + * @param null|string $scheme + * @return string + */ + protected function getScheme($scheme = null) + { + return $scheme ? $scheme . '://' : ''; + } + + /** + * Read directory recursively + * + * @param string $path + * @return string[] + * @throws FileSystemException + */ + public function readDirectoryRecursively($path = null) + { + $result = []; + $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS; + try { + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path, $flags), + \RecursiveIteratorIterator::CHILD_FIRST + ); + /** @var \FilesystemIterator $file */ + foreach ($iterator as $file) { + $result[] = $file->getPathname(); + } + } catch (\Exception $e) { + throw new FileSystemException(new Phrase($e->getMessage()), $e); + } + return $result; + } + + /** + * Get real path + * + * @param string $path + * + * @return string|bool + */ + public function getRealPath($path) + { + return realpath($path); + } + + /** + * Return correct path for link + * + * @param string $path + * @return mixed + */ + public function getRealPathSafety($path) + { + if (strpos($path, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) === false) { + return $path; + } + + //Removing redundant directory separators. + $path = preg_replace( + '/\\' . DIRECTORY_SEPARATOR . '\\' . DIRECTORY_SEPARATOR . '+/', + DIRECTORY_SEPARATOR, + $path + ); + $pathParts = explode(DIRECTORY_SEPARATOR, $path); + $realPath = []; + foreach ($pathParts as $pathPart) { + if ($pathPart == '.') { + continue; + } + if ($pathPart == '..') { + array_pop($realPath); + continue; + } + $realPath[] = $pathPart; + } + return implode(DIRECTORY_SEPARATOR, $realPath); + } +} diff --git a/lib/internal/Magento/Framework/Filesystem/Io/File.php b/lib/internal/Magento/Framework/Filesystem/Io/File.php index 8fec7f7630257..2e81325c8ec57 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/File.php @@ -3,10 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Filesystem\Io; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; + /** * Filesystem client + * * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class File extends AbstractIo @@ -186,7 +191,7 @@ public function streamWriteCsv(array $row, $delimiter = ',', $enclosure = '"') * Security enhancement for CSV data processing by Excel-like applications. * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 * - * @var $value string|\Magento\Framework\Phrase + * @var $value string|Phrase */ foreach ($row as $key => $value) { if (!is_string($value)) { @@ -201,6 +206,7 @@ public function streamWriteCsv(array $row, $delimiter = ',', $enclosure = '"') /** * Close an open file pointer + * * Set chmod on a file * * @return bool @@ -328,6 +334,7 @@ public function rmdir($dir, $recursive = false) /** * Delete a directory recursively + * * @param string $dir * @param bool $recursive * @return bool @@ -405,8 +412,8 @@ public function pwd() * * @param string $dir * @return true - * @throws \Exception * @SuppressWarnings(PHPMD.ShortMethodName) + * @throws LocalizedException */ public function cd($dir) { @@ -415,7 +422,9 @@ public function cd($dir) $this->_cwd = realpath($dir); return true; } else { - throw new \Exception('Unable to list current working directory.'); + throw new LocalizedException( + new Phrase('Unable to list current working directory.') + ); } } @@ -479,7 +488,7 @@ public function write($filename, $src, $mode = null) } else { $result = @file_put_contents($filename, $src); } - if ($mode !== null && $result) { + if ($mode !== null && $result !== false) { @chmod($filename, $mode); } $this->_iwd(); @@ -553,7 +562,7 @@ public function createDestinationDir($path) * @param string $folder * @param int $mode * @return true - * @throws \Exception + * @throws LocalizedException */ public function checkAndCreateFolder($folder, $mode = 0777) { @@ -564,7 +573,9 @@ public function checkAndCreateFolder($folder, $mode = 0777) $this->checkAndCreateFolder(dirname($folder), $mode); } if (!is_dir($folder) && !$this->mkdir($folder, $mode)) { - throw new \Exception("Unable to create directory '{$folder}'. Access forbidden."); + throw new LocalizedException( + new Phrase("Unable to create directory '{$folder}'. Access forbidden.") + ); } return true; } @@ -672,7 +683,7 @@ public static function chmodRecursive($dir, $mode) * * @param string|null $grep * @return array - * @throws \Exception + * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ShortMethodName) */ @@ -685,7 +696,9 @@ public function ls($grep = null) } elseif (is_dir($this->_iwd)) { $dir = $this->_iwd; } else { - throw new \Exception('Unable to list current working directory.'); + throw new LocalizedException( + new Phrase('Unable to list current working directory.') + ); } $list = []; @@ -742,7 +755,9 @@ public function ls($grep = null) } closedir($dirHandler); } else { - throw new \Exception('Unable to list current working directory. Access forbidden.'); + throw new LocalizedException( + new Phrase('Unable to list current working directory. Access forbidden.') + ); } return $list; diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php index 8fc57f458334e..a851d30ef930e 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Driver/HttpTest.php @@ -3,12 +3,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Framework\Filesystem\Test\Unit\Driver; -use \Magento\Framework\Filesystem\Driver\Http; +use Magento\Framework\Filesystem\Driver\Http; +use PHPUnit\Framework\TestCase; -class HttpTest extends \PHPUnit\Framework\TestCase +/** + * Verify HttpTest class. + */ +class HttpTest extends TestCase { /** @var array Result of get_headers() function */ public static $headers; @@ -22,6 +27,9 @@ class HttpTest extends \PHPUnit\Framework\TestCase /** @var bool Result of fsockopen() function */ public static $fsockopen; + /** + * @inheritDoc + */ protected function setUp() { require_once __DIR__ . '/../_files/http_mock.php'; @@ -33,35 +41,49 @@ protected function setUp() } /** + * Verify IsExists. + * + * @param string $status + * @param bool $result * @dataProvider dataProviderForTestIsExists + * @return void */ - public function testIsExists($status, $result) + public function testIsExists(string $status, bool $result): void { self::$headers = [$status]; $this->assertEquals($result, (new Http())->isExists('')); } /** + * Data provider fot test IsExists. + * * @return array */ - public function dataProviderForTestIsExists() + public function dataProviderForTestIsExists(): array { return [['200 OK', true], ['404 Not Found', false]]; } /** + * Verify Stat. + * + * @param array $headers + * @param array $result * @dataProvider dataProviderForTestStat + * @return void */ - public function testStat($headers, $result) + public function testStat(array $headers, array $result): void { self::$headers = $headers; $this->assertEquals($result, (new Http())->stat('')); } /** + * Data provider for test Stat. + * * @return array */ - public function dataProviderForTestStat() + public function dataProviderForTestStat(): array { $headers1 = [ 'Content-Length' => 128, @@ -106,45 +128,87 @@ protected function _resultForStat($nonEmptyValues = []) return array_merge($result, $nonEmptyValues); } - public function testFileGetContents() + /** + * Verify File get contents. + * + * @throws \Magento\Framework\Exception\FileSystemException + * @return void + */ + public function testFileGetContents(): void { $content = 'some content'; self::$fileGetContents = $content; $this->assertEquals($content, (new Http())->fileGetContents('')); } - public function testFileGetContentsNoContent() + /** + * Verify File get contents without content. + * + * @throws \Magento\Framework\Exception\FileSystemException + * @return void + */ + public function testFileGetContentsNoContent(): void { $content = ''; self::$fileGetContents = ''; $this->assertEquals($content, (new Http())->fileGetContents('')); } - public function testFilePutContents() + /** + * Verify File put contents. + * + * @throws \Magento\Framework\Exception\FileSystemException + * @return void + */ + public function testFilePutContents(): void { self::$filePutContents = true; $this->assertTrue((new Http())->filePutContents('', '')); } /** + * Verify file put contents without content. + * + * @throws \Magento\Framework\Exception\FileSystemException + * @return void + */ + public function testFilePutContentsNoContent(): void + { + self::$filePutContents = 0; + $this->assertEquals(0, (new Http())->filePutContents('', '')); + } + + /** + * Verify File put contents if is fail. + * * @expectedException \Magento\Framework\Exception\FileSystemException + * @return void */ - public function testFilePutContentsFail() + public function testFilePutContentsFail(): void { self::$filePutContents = false; (new Http())->filePutContents('', ''); } /** + * Verify File open invalid url. + * * @expectedException \Magento\Framework\Exception\FileSystemException * @expectedExceptionMessage The download URL is incorrect. Verify and try again. + * @return void */ - public function testFileOpenInvalidUrl() + public function testFileOpenInvalidUrl(): void { (new Http())->fileOpen('', ''); } - public function testFileOpen() + /** + * Verify File open. + * + * @throws \Magento\Framework\Exception\FileSystemException + * @return void + */ + public function testFileOpen(): void { $fsockopenResult = 'resource'; self::$fsockopen = $fsockopenResult; diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index caa080c02e255..df236faf8173b 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -75,16 +75,6 @@ public function open($filename) $this->_getCallback('create', null, sprintf('Unsupported image format. File: %s', $this->_fileName)), $this->_fileName ); - $fileType = $this->getImageType(); - if (in_array($fileType, [IMAGETYPE_PNG, IMAGETYPE_GIF])) { - $this->_keepTransparency = true; - if ($this->_imageHandler) { - $isAlpha = $this->checkAlpha($this->_fileName); - if ($isAlpha) { - $this->_fillBackgroundColor($this->_imageHandler); - } - } - } } /** diff --git a/lib/internal/Magento/Framework/Locale/Config.php b/lib/internal/Magento/Framework/Locale/Config.php index c2d0147c7fdc8..08f66e25be773 100644 --- a/lib/internal/Magento/Framework/Locale/Config.php +++ b/lib/internal/Magento/Framework/Locale/Config.php @@ -108,6 +108,7 @@ class Config implements \Magento\Framework\Locale\ConfigInterface 'es_VE', /*Spanish (Venezuela)*/ 'en_IE', /*English (Ireland)*/ 'es_BO', /*Spanish (Bolivia)*/ + 'es_US', /*Spanish (United States)*/ ]; /** diff --git a/lib/internal/Magento/Framework/MessageQueue/Topology/Config.php b/lib/internal/Magento/Framework/MessageQueue/Topology/Config.php index 7add2bd286e1d..10fce32abade0 100644 --- a/lib/internal/Magento/Framework/MessageQueue/Topology/Config.php +++ b/lib/internal/Magento/Framework/MessageQueue/Topology/Config.php @@ -24,9 +24,9 @@ class Config implements ConfigInterface private $exchangeIterator; /** - * Exchange config data iterator. + * Queue config data iterator. * - * @var ExchangeIterator + * @var QueueIterator */ private $queueIterator; @@ -43,7 +43,7 @@ public function __construct(ExchangeIterator $exchangeIterator, QueueIterator $q } /** - * {@inheritdoc} + * @inheritdoc */ public function getExchange($name, $connection) { @@ -63,7 +63,7 @@ public function getExchange($name, $connection) } /** - * {@inheritdoc} + * @inheritdoc */ public function getExchanges() { @@ -71,7 +71,7 @@ public function getExchanges() } /** - * {@inheritdoc} + * @inheritdoc */ public function getQueues() { diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSample.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSample.php index 1d78f9ed0a7d8..544165774db82 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSample.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSample.php @@ -22,4 +22,20 @@ public function getName() { return ''; } + + /** + * @inheritdoc + */ + public function getWithNull() + { + return null; + } + + /** + * @inheritdoc + */ + public function getOnlyNull() + { + return null; + } } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSampleInterface.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSampleInterface.php index db2fbd19736bf..647c1a7c1dfbd 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSampleInterface.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/Fixture/TSampleInterface.php @@ -18,4 +18,16 @@ public function getPropertyName(); * Doc block without return tag. */ public function getName(); + + /** + * return annotation with a null type at first position + * @return null|string + */ + public function getWithNull(); + + /** + * return annotation with only null type + * @return null + */ + public function getOnlyNull(); } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php index 1a8702c0e1c5b..2ae0424b13e19 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/TypeProcessorTest.php @@ -364,6 +364,25 @@ public function testGetReturnTypeWithoutReturnTag() $this->typeProcessor->getGetterReturnType($methodReflection); } + /** + * Checks a case when method return annotation has a null-type at first position, + * and a valid type at second. + */ + public function testGetReturnTypeNullAtFirstPos() + { + $expected = [ + 'type' => 'string', + 'isRequired' => false, + 'description' => null, + 'parameterCount' => 0 + ]; + + $classReflection = new ClassReflection(TSample::class); + $methodReflection = $classReflection->getMethod('getWithNull'); + + self::assertEquals($expected, $this->typeProcessor->getGetterReturnType($methodReflection)); + } + /** * Simple and complex data provider * diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 9571fa53547ab..11c9e605577b1 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -286,7 +286,14 @@ public function getGetterReturnType($methodReflection) { $returnAnnotation = $this->getMethodReturnAnnotation($methodReflection); $types = $returnAnnotation->getTypes(); - $returnType = current($types); + $returnType = null; + foreach ($types as $type) { + if ($type !== 'null') { + $returnType = $type; + break; + } + } + $nullable = in_array('null', $types); return [ @@ -312,6 +319,7 @@ public function getExceptions($methodReflection) if (is_array($throwsTypes)) { /** @var $throwsType \Zend\Code\Reflection\DocBlock\Tag\ThrowsTag */ foreach ($throwsTypes as $throwsType) { + // phpcs:ignore $exceptions = array_merge($exceptions, $throwsType->getTypes()); } } @@ -513,13 +521,15 @@ public function getParamType(ParameterReflection $param) { $type = $param->detectType(); if ($type === 'null') { - throw new \LogicException(sprintf( - '@param annotation is incorrect for the parameter "%s" in the method "%s:%s".' - . ' First declared type should not be null. E.g. string|null', - $param->getName(), - $param->getDeclaringClass()->getName(), - $param->getDeclaringFunction()->name - )); + throw new \LogicException( + sprintf( + '@param annotation is incorrect for the parameter "%s" in the method "%s:%s".' + . ' First declared type should not be null. E.g. string|null', + $param->getName(), + $param->getDeclaringClass()->getName(), + $param->getDeclaringFunction()->name + ) + ); } if ($type === 'array') { // try to determine class, if it's array of objects diff --git a/lib/internal/Magento/Framework/Session/SaveHandler.php b/lib/internal/Magento/Framework/Session/SaveHandler.php index 7959130d1e41c..b43468caa5659 100644 --- a/lib/internal/Magento/Framework/Session/SaveHandler.php +++ b/lib/internal/Magento/Framework/Session/SaveHandler.php @@ -3,13 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\Session; use Magento\Framework\Session\Config\ConfigInterface; -use \Magento\Framework\Exception\SessionException; +use Magento\Framework\Exception\SessionException; /** - * Magento session save handler + * Magento session save handler. */ class SaveHandler implements SaveHandlerInterface { @@ -21,8 +22,21 @@ class SaveHandler implements SaveHandlerInterface protected $saveHandlerAdapter; /** - * Constructor - * + * @var SaveHandlerFactory + */ + private $saveHandlerFactory; + + /** + * @var ConfigInterface + */ + private $sessionConfig; + + /** + * @var string + */ + private $defaultHandler; + + /** * @param SaveHandlerFactory $saveHandlerFactory * @param ConfigInterface $sessionConfig * @param string $default @@ -32,23 +46,13 @@ public function __construct( ConfigInterface $sessionConfig, $default = self::DEFAULT_HANDLER ) { - /** - * Session handler - * - * Save handler may be set to custom value in deployment config, which will override everything else. - * Otherwise, try to read PHP settings for session.save_handler value. Otherwise, use 'files' as default. - */ - $saveMethod = $sessionConfig->getOption('session.save_handler') ?: $default; - - try { - $this->saveHandlerAdapter = $saveHandlerFactory->create($saveMethod); - } catch (SessionException $e) { - $this->saveHandlerAdapter = $saveHandlerFactory->create($default); - } + $this->saveHandlerFactory = $saveHandlerFactory; + $this->sessionConfig = $sessionConfig; + $this->defaultHandler = $default; } /** - * Open Session - retrieve resources + * Open Session - retrieve resources. * * @param string $savePath * @param string $name @@ -56,32 +60,32 @@ public function __construct( */ public function open($savePath, $name) { - return $this->saveHandlerAdapter->open($savePath, $name); + return $this->callSafely('open', $savePath, $name); } /** - * Close Session - free resources + * Close Session - free resources. * * @return bool */ public function close() { - return $this->saveHandlerAdapter->close(); + return $this->callSafely('close'); } /** - * Read session data + * Read session data. * * @param string $sessionId * @return string */ public function read($sessionId) { - return $this->saveHandlerAdapter->read($sessionId); + return $this->callSafely('read', $sessionId); } /** - * Write Session - commit data to resource + * Write Session - commit data to resource. * * @param string $sessionId * @param string $data @@ -89,23 +93,22 @@ public function read($sessionId) */ public function write($sessionId, $data) { - return $this->saveHandlerAdapter->write($sessionId, $data); + return $this->callSafely('write', $sessionId, $data); } /** - * Destroy Session - remove data from resource for given session id + * Destroy Session - remove data from resource for given session id. * * @param string $sessionId * @return bool */ public function destroy($sessionId) { - return $this->saveHandlerAdapter->destroy($sessionId); + return $this->callSafely('destroy', $sessionId); } /** - * Garbage Collection - remove old session data older - * than $maxLifetime (in seconds) + * Garbage Collection - remove old session data older than $maxLifetime (in seconds). * * @param int $maxLifetime * @return bool @@ -113,6 +116,30 @@ public function destroy($sessionId) */ public function gc($maxLifetime) { - return $this->saveHandlerAdapter->gc($maxLifetime); + return $this->callSafely('gc', $maxLifetime); + } + + /** + * Call save handler adapter method. + * + * In case custom handler failed, default files handler is used. + * + * @param string $method + * @param mixed $arguments + * + * @return mixed + */ + private function callSafely(string $method, ...$arguments) + { + try { + if ($this->saveHandlerAdapter === null) { + $saveMethod = $this->sessionConfig->getOption('session.save_handler') ?: $this->defaultHandler; + $this->saveHandlerAdapter = $this->saveHandlerFactory->create($saveMethod); + } + return $this->saveHandlerAdapter->{$method}(...$arguments); + } catch (SessionException $exception) { + $this->saveHandlerAdapter = $this->saveHandlerFactory->create($this->defaultHandler); + return $this->saveHandlerAdapter->{$method}(...$arguments); + } } } diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php index 2568a5ccf21c1..0791c89ab793a 100644 --- a/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php +++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Timezone.php @@ -206,25 +206,9 @@ public function scopeDate($scope = null, $date = null, $includeTime = false) case ($date instanceof \DateTimeImmutable): $date = $date->setTimezone($timezone); break; - case (!is_numeric($date)): - $timeType = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE; - $formatter = new \IntlDateFormatter( - $this->_localeResolver->getLocale(), - \IntlDateFormatter::SHORT, - $timeType, - $timezone - ); - $timestamp = $formatter->parse($date); - $date = $timestamp - ? (new \DateTime('@' . $timestamp))->setTimezone($timezone) - : new \DateTime($date, $timezone); - break; - case (is_numeric($date)): - $date = new \DateTime('@' . $date); - $date = $date->setTimezone($timezone); - break; default: - $date = new \DateTime($date, $timezone); + $date = new \DateTime(is_numeric($date) ? '@' . $date : $date); + $date->setTimezone($timezone); break; } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php index 566992c70b5e3..12ba34778b66e 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php @@ -314,14 +314,15 @@ public function scopeDateDataProvider(): array return [ ['2018-10-20 00:00:00', 'UTC', 'en_US', '2018-10-20 00:00:00'], - ['2018-10-20 00:00:00', 'America/Los_Angeles', 'en_US', '2018-10-20 00:00:00'], - ['2018-10-20 00:00:00', 'Asia/Qatar', 'en_US', '2018-10-20 00:00:00'], + ['2018-10-20 00:00:00', 'America/Los_Angeles', 'en_US', '2018-10-19 17:00:00'], + ['2018-10-20 00:00:00', 'Asia/Qatar', 'en_US', '2018-10-20 03:00:00'], + ['2018-10-20 00:00:00', 'America/Los_Angeles', 'en_GB', '2018-10-19 17:00:00'], ['10/20/18 00:00', 'UTC', 'en_US', '2018-10-20 00:00:00'], - ['10/20/18 00:00', 'America/Los_Angeles', 'en_US', '2018-10-20 00:00:00'], - ['10/20/18 00:00', 'Asia/Qatar', 'en_US', '2018-10-20 00:00:00'], - ['20/10/18 00:00', 'UTC', 'fr_FR', '2018-10-20 00:00:00'], - ['20/10/18 00:00', 'America/Los_Angeles', 'fr_FR', '2018-10-20 00:00:00'], - ['20/10/18 00:00', 'Asia/Qatar', 'fr_FR', '2018-10-20 00:00:00'], + ['10/20/18 00:00', 'America/Los_Angeles', 'en_US', '2018-10-19 17:00:00'], + ['10/20/18 00:00', 'Asia/Qatar', 'en_US', '2018-10-20 03:00:00'], + ['10/20/18 00:00', 'UTC', 'fr_FR', '2018-10-20 00:00:00'], + ['10/20/18 00:00', 'America/Los_Angeles', 'fr_FR', '2018-10-19 17:00:00'], + ['10/20/18 00:00', 'Asia/Qatar', 'fr_FR', '2018-10-20 03:00:00'], [1539993600, 'UTC', 'en_US', '2018-10-20 00:00:00'], [1539993600, 'America/Los_Angeles', 'en_US', '2018-10-19 17:00:00'], [1539993600, 'Asia/Qatar', 'en_US', '2018-10-20 03:00:00'], diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/Container.php b/lib/internal/Magento/Framework/View/Layout/Generator/Container.php index d220808e21455..075f8148a4504 100644 --- a/lib/internal/Magento/Framework/View/Layout/Generator/Container.php +++ b/lib/internal/Magento/Framework/View/Layout/Generator/Container.php @@ -7,6 +7,9 @@ use Magento\Framework\View\Layout; +/** + * Layout Container Class + */ class Container implements Layout\GeneratorInterface { /**#@+ @@ -39,10 +42,11 @@ class Container implements Layout\GeneratorInterface 'table', 'tfoot', 'ul', + 'article', ]; /** - * {@inheritdoc} + * @inheritdoc * * @return string */ @@ -95,8 +99,12 @@ public function generateContainer( } /** + * Validate container options + * * @param array $options + * * @return void + * * @throws \Magento\Framework\Exception\LocalizedException */ protected function validateOptions($options) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/ContainerTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/ContainerTest.php index 68c673e95a82d..1752847943dd3 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/ContainerTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Generator/ContainerTest.php @@ -138,6 +138,26 @@ public function processDataProvider() ['first_container', Container::CONTAINER_OPT_HTML_ID, 'dd_id'], ], 'setAttributeCalls' => 3, + ], + 'Article as allowed container tag' => [ + 'structureElements' => [ + 'first_container' => [ + 'container', + [ + 'attributes' => [ + Container::CONTAINER_OPT_HTML_TAG => 'article', + Container::CONTAINER_OPT_HTML_CLASS => 'article_class', + Container::CONTAINER_OPT_HTML_ID => 'article_id', + ] + ], + ], + ], + 'setAttributeData' => [ + ['first_container', Container::CONTAINER_OPT_HTML_TAG, 'article'], + ['first_container', Container::CONTAINER_OPT_HTML_CLASS, 'article_class'], + ['first_container', Container::CONTAINER_OPT_HTML_ID, 'article_id'], + ], + 'setAttributeCalls' => 3, ] ]; } diff --git a/lib/web/css/source/lib/_resets.less b/lib/web/css/source/lib/_resets.less index a680c91af3dbe..4c3d4476c2c80 100644 --- a/lib/web/css/source/lib/_resets.less +++ b/lib/web/css/source/lib/_resets.less @@ -48,14 +48,14 @@ } img { + max-width: 100%; + height: auto; border: 0; } - img, - object, video, - embed { - max-height: 100%; + embed, + object { max-width: 100%; } diff --git a/pub/errors/default/report.phtml b/pub/errors/default/report.phtml index 546b96605ec1b..ecf43d57550ed 100644 --- a/pub/errors/default/report.phtml +++ b/pub/errors/default/report.phtml @@ -49,7 +49,7 @@ <div class="field telephone"> <label for="telephone" class="label">Telephone</label> <div class="control"> - <input type="text" name="telephone" id="telephone" value="<?= $this->postData['telephone'] ?>" title="Telephone" class="input-text" /> + <input type="tel" name="telephone" id="telephone" value="<?= $this->postData['telephone'] ?>" title="Telephone" class="input-text" /> </div> </div> <div class="field comment"> diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 23f8a13c8bfe8..535040f942b89 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -7,6 +7,8 @@ namespace Magento\Setup\Model; use Magento\Backend\Setup\ConfigOptionsList as BackendConfigOptionsList; +use Magento\Framework\App\Cache\Type\Block as BlockCache; +use Magento\Framework\App\Cache\Type\Layout as LayoutCache; use Magento\Framework\App\DeploymentConfig\Reader; use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\Filesystem\DirectoryList; @@ -35,6 +37,7 @@ use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\Setup\UpgradeDataInterface; use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\PageCache\Model\Cache\Type as PageCache; use Magento\Setup\Console\Command\InstallCommand; use Magento\Setup\Controller\ResponseTypeInterface; use Magento\Setup\Model\ConfigModel as SetupConfigModel; @@ -336,7 +339,7 @@ public function install($request) } $script[] = ['Installing database schema:', 'installSchema', [$request]]; $script[] = ['Installing user configuration...', 'installUserConfig', [$request]]; - $script[] = ['Enabling caches:', 'enableCaches', []]; + $script[] = ['Enabling caches:', 'updateCaches', [true]]; $script[] = ['Installing data...', 'installDataFixtures', [$request]]; if (!empty($request[InstallCommand::INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX])) { $script[] = [ @@ -866,6 +869,12 @@ private function convertationOfOldScriptsIsAllowed(array $request) */ public function installDataFixtures(array $request = []) { + $frontendCaches = [ + PageCache::TYPE_IDENTIFIER, + BlockCache::TYPE_IDENTIFIER, + LayoutCache::TYPE_IDENTIFIER, + ]; + /** @var \Magento\Framework\Registry $registry */ $registry = $this->objectManagerProvider->get()->get(\Magento\Framework\Registry::class); //For backward compatibility in install and upgrade scripts with enabled parallelization. @@ -876,7 +885,11 @@ public function installDataFixtures(array $request = []) $setup = $this->dataSetupFactory->create(); $this->checkFilePermissionsForDbUpgrade(); $this->log->log('Data install/update:'); + $this->log->log('Disabling caches:'); + $this->updateCaches(false, $frontendCaches); $this->handleDBSchemaData($setup, 'data', $request); + $this->log->log('Enabling caches:'); + $this->updateCaches(true, $frontendCaches); $registry->unregister('setup-mode-enabled'); } @@ -1248,23 +1261,39 @@ public function uninstall() } /** - * Enables caches after installing application + * Enable or disable caches for specific types that are available * - * @return void + * If no types are specified then it will enable or disable all available types + * Note this is called by install() via callback. * - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) Called by install() via callback. + * @param bool $isEnabled + * @param array $types + * @return void */ - private function enableCaches() + private function updateCaches($isEnabled, $types = []) { /** @var \Magento\Framework\App\Cache\Manager $cacheManager */ $cacheManager = $this->objectManagerProvider->get()->create(\Magento\Framework\App\Cache\Manager::class); - $types = $cacheManager->getAvailableTypes(); - $enabledTypes = $cacheManager->setEnabled($types, true); - $cacheManager->clean($enabledTypes); + + $availableTypes = $cacheManager->getAvailableTypes(); + $types = empty($types) ? $availableTypes : array_intersect($availableTypes, $types); + $enabledTypes = $cacheManager->setEnabled($types, $isEnabled); + if ($isEnabled) { + $cacheManager->clean($enabledTypes); + } + + // Only get statuses of specific cache types + $cacheStatus = array_filter( + $cacheManager->getStatus(), + function (string $key) use ($types) { + return in_array($key, $types); + }, + ARRAY_FILTER_USE_KEY + ); $this->log->log('Current status:'); // phpcs:ignore Magento2.Functions.DiscouragedFunction - $this->log->log(print_r($cacheManager->getStatus(), true)); + $this->log->log(print_r($cacheStatus, true)); } /** diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php index b3a2f14aa922a..ae957adb09d17 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Setup\Module\Di\Code\Reader; @@ -12,8 +13,6 @@ /** * Class ClassesScanner - * - * @package Magento\Setup\Module\Di\Code\Reader */ class ClassesScanner implements ClassesScannerInterface { @@ -100,7 +99,7 @@ public function getList($path) */ private function extract(\RecursiveIteratorIterator $recursiveIterator) { - $classes = [[]]; + $classes = []; foreach ($recursiveIterator as $fileItem) { /** @var $fileItem \SplFileInfo */ if ($fileItem->isDir() || $fileItem->getExtension() !== 'php' || $fileItem->getBasename()[0] == '.') { @@ -113,28 +112,29 @@ private function extract(\RecursiveIteratorIterator $recursiveIterator) } } $fileScanner = new FileClassScanner($fileItemPath); - $classNames = $fileScanner->getClassNames(); - $this->includeClasses($classNames, $fileItemPath); - $classes [] = $classNames; + $className = $fileScanner->getClassName(); + if (!empty($className)) { + $this->includeClass($className, $fileItemPath); + $classes[] = $className; + } } - return array_merge(...$classes); + + return $classes; } /** - * Include classes from file path + * Include class from file path. * - * @param array $classNames + * @param string $className * @param string $fileItemPath * @return bool Whether the class is included or not */ - private function includeClasses(array $classNames, $fileItemPath) + private function includeClass(string $className, string $fileItemPath): bool { - foreach ($classNames as $className) { - if (!class_exists($className)) { - // phpcs:ignore - require_once $fileItemPath; - return true; - } + if (!class_exists($className)) { + // phpcs:ignore + require_once $fileItemPath; + return true; } return false; } diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/FileClassScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileClassScanner.php index 9a91006564d7f..c5e5230d253cc 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Reader/FileClassScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileClassScanner.php @@ -3,13 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Setup\Module\Di\Code\Reader; /** * Class FileClassScanner - * - * @package Magento\Setup\Module\Di\Code\Reader */ class FileClassScanner { @@ -20,9 +19,10 @@ class FileClassScanner ]; private const ALLOWED_OPEN_BRACES_TOKENS = [ - T_CURLY_OPEN => true, + T_CURLY_OPEN => true, T_DOLLAR_OPEN_CURLY_BRACES => true, - T_STRING_VARNAME => true]; + T_STRING_VARNAME => true + ]; /** * The filename of the file to introspect @@ -32,11 +32,11 @@ class FileClassScanner private $filename; /** - * The list of classes found in the file. + * The class name found in the file. * * @var bool */ - private $classNames = false; + private $className = false; /** * @var array @@ -75,6 +75,19 @@ public function getFileContents() return file_get_contents($this->filename); } + /** + * Retrieves the first class found in a class file. + * + * @return string + */ + public function getClassName(): string + { + if ($this->className === false) { + $this->className = $this->extract(); + } + return $this->className; + } + /** * Extracts the fully qualified class name from a file. * @@ -85,11 +98,10 @@ public function getFileContents() * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) - * @return array + * @return string */ - private function extract() + private function extract(): string { - $classes = []; $namespaceParts = []; $class = ''; $triggerClass = false; @@ -117,6 +129,9 @@ private function extract() } $namespaceParts[] = $token[1]; + // `class` token is not used with a valid class name + } elseif ($triggerClass && !$tokenIsArray) { + $triggerClass = false; // The class keyword was found in the last loop } elseif ($triggerClass && $token[0] === T_STRING) { $triggerClass = false; @@ -125,27 +140,26 @@ private function extract() switch ($token[0]) { case T_NAMESPACE: - // Current loop contains the namespace keyword. Between this and the semicolon is the namespace + // Current loop contains the namespace keyword. Between this and the semicolon is the namespace $triggerNamespace = true; $namespaceParts = []; $bracedNamespace = $this->isBracedNamespace($index); break; case T_CLASS: - // Current loop contains the class keyword. Next loop will have the class name itself. + // Current loop contains the class keyword. Next loop will have the class name itself. if ($braceLevel == 0 || ($bracedNamespace && $braceLevel == 1)) { $triggerClass = true; } break; } - // We have a class name, let's concatenate and store it! + // We have a class name, let's concatenate and return it! if ($class !== '') { $fqClassName = trim(join('', $namespaceParts)) . trim($class); - $classes[] = $fqClassName; - $class = ''; + return $fqClassName; } } - return $classes; + return $class; } /** @@ -173,19 +187,4 @@ private function isBracedNamespace($index) } throw new InvalidFileException('Could not find namespace termination'); } - - /** - * Retrieves the first class found in a class file. - * - * The return value is in an array format so it retains the same usage as the FileScanner. - * - * @return array - */ - public function getClassNames() - { - if ($this->classNames === false) { - $this->classNames = $this->extract(); - } - return $this->classNames; - } } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index e600002d53560..2b992c30615c2 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -307,8 +307,9 @@ public function testInstall(array $request, array $logMessages) $dataSetup->expects($this->any())->method('getConnection')->willReturn($connection); $cacheManager = $this->createMock(\Magento\Framework\App\Cache\Manager::class); $cacheManager->expects($this->any())->method('getAvailableTypes')->willReturn(['foo', 'bar']); - $cacheManager->expects($this->once())->method('setEnabled')->willReturn(['foo', 'bar']); - $cacheManager->expects($this->any())->method('clean'); + $cacheManager->expects($this->exactly(3))->method('setEnabled')->willReturn(['foo', 'bar']); + $cacheManager->expects($this->exactly(3))->method('clean'); + $cacheManager->expects($this->exactly(3))->method('getStatus')->willReturn(['foo' => 1, 'bar' => 1]); $appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->disableArgumentCloning() @@ -382,6 +383,7 @@ public function testInstall(array $request, array $logMessages) /** * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function installDataProvider() { @@ -410,15 +412,20 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [''], + [print_r(['foo' => 1, 'bar' => 1], true)], ['Installing data...'], ['Data install/update:'], + ['Disabling caches:'], + ['Current status:'], + [print_r([], true)], ['Module \'Foo_One\':'], ['Module \'Bar_Two\':'], ['Data post-updates:'], ['Module \'Foo_One\':'], ['Module \'Bar_Two\':'], - //['Installing admin user...'], + ['Enabling caches:'], + ['Current status:'], + [print_r([], true)], ['Caches clearing:'], ['Cache cleared successfully'], ['Disabling Maintenance Mode:'], @@ -456,14 +463,20 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [''], + [print_r(['foo' => 1, 'bar' => 1], true)], ['Installing data...'], ['Data install/update:'], + ['Disabling caches:'], + ['Current status:'], + [print_r([], true)], ['Module \'Foo_One\':'], ['Module \'Bar_Two\':'], ['Data post-updates:'], ['Module \'Foo_One\':'], ['Module \'Bar_Two\':'], + ['Enabling caches:'], + ['Current status:'], + [print_r([], true)], ['Installing admin user...'], ['Caches clearing:'], ['Cache cleared successfully'], diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/FileClassScannerTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/FileClassScannerTest.php index 5bc7fd82b3251..c50c024aefe8f 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/FileClassScannerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/FileClassScannerTest.php @@ -7,23 +7,22 @@ use Magento\Setup\Module\Di\Code\Reader\FileClassScanner; use Magento\Setup\Module\Di\Code\Reader\InvalidFileException; +use PHPUnit\Framework\MockObject\MockObject; class FileClassScannerTest extends \PHPUnit\Framework\TestCase { - public function testInvalidFileThrowsException() { $this->expectException(InvalidFileException::class); - new FileClassScanner(false); + new FileClassScanner(''); } public function testEmptyArrayForFileWithoutNamespaceOrClass() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php echo 'hello world'; @@ -35,17 +34,16 @@ public function testEmptyArrayForFileWithoutNamespaceOrClass() ); /** @var $scanner FileClassScanner */ - $result = $scanner->getClassNames(); - self::assertCount(0, $result); + $result = $scanner->getClassName(); + self::assertEmpty($result); } public function testGetClassName() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php class ThisIsATest { @@ -53,21 +51,18 @@ class ThisIsATest { } PHP ); - /** @var $scanner FileClassScanner */ - - $result = $scanner->getClassNames(); - self::assertCount(1, $result); - self::assertContains('ThisIsATest', $result); + /** @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + self::assertEquals('ThisIsATest', $result); } public function testGetClassNameAndSingleNamespace() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php namespace NS; @@ -77,21 +72,18 @@ class ThisIsMyTest { } PHP ); - /** @var $scanner FileClassScanner */ - $result = $scanner->getClassNames(); - - self::assertCount(1, $result); - self::assertContains('NS\ThisIsMyTest', $result); + /** @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + self::assertEquals('NS\ThisIsMyTest', $result); } public function testGetClassNameAndMultiNamespace() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php namespace This\Is\My\Ns; @@ -102,29 +94,26 @@ public function __construct() { \This\Is\Another\Ns::class; } - + public function test() { - + } } PHP ); - /** @var $scanner FileClassScanner */ - - $result = $scanner->getClassNames(); - self::assertCount(1, $result); - self::assertContains('This\Is\My\Ns\ThisIsMyTest', $result); + /** @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + self::assertEquals('This\Is\My\Ns\ThisIsMyTest', $result); } public function testGetMultiClassNameAndMultiNamespace() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php namespace This\Is\My\Ns; @@ -136,10 +125,10 @@ public function __construct() \$this->get(\This\Is\Another\Ns::class)->method(); self:: class; } - + public function test() { - + } } @@ -149,37 +138,34 @@ class ThisIsForBreaking { PHP ); - /** @var $scanner FileClassScanner */ - $result = $scanner->getClassNames(); - - self::assertCount(2, $result); - self::assertContains('This\Is\My\Ns\ThisIsMyTest', $result); - self::assertContains('This\Is\My\Ns\ThisIsForBreaking', $result); + /** @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + // only a single class should be in the file + self::assertEquals('This\Is\My\Ns\ThisIsMyTest', $result); } public function testBracketedNamespacesAndClasses() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php namespace This\Is\My\Ns { class ThisIsMyTest { - + public function __construct() { \This\Is\Another\Ns::class; self:: class; } - + } - + class ThisIsForBreaking { } @@ -189,27 +175,24 @@ class ThisIsForBreaking class ThisIsNotMyTest { - } + } } PHP ); - /** @var $scanner FileClassScanner */ - - $result = $scanner->getClassNames(); - self::assertCount(3, $result); - self::assertContains('This\Is\My\Ns\ThisIsMyTest', $result); - self::assertContains('This\Is\My\Ns\ThisIsForBreaking', $result); - self::assertContains('This\Is\Not\My\Ns\ThisIsNotMyTest', $result); + /** @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + // only a single class should in the file + self::assertEquals('This\Is\My\Ns\ThisIsMyTest', $result); } public function testMultipleClassKeywordsInMiddleOfFileWithStringVariableParsing() { - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn(<<<'PHP' + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<'PHP' <?php namespace This\Is\My\Ns; @@ -236,22 +219,20 @@ protected function secondMethod() ); /* @var $scanner FileClassScanner */ - $result = $scanner->getClassNames(); - - self::assertCount(1, $result); + $result = $scanner->getClassName(); + self::assertEquals('This\Is\My\Ns\ThisIsMyTest', $result); } public function testInvalidPHPCodeThrowsExceptionWhenCannotDetermineBraceOrSemiColon() { $this->expectException(InvalidFileException::class); - $scanner = $this->getMockBuilder(FileClassScanner::class)->disableOriginalConstructor()->setMethods([ - 'getFileContents' - ])->getMock(); - $scanner->expects(self::once())->method('getFileContents')->willReturn( - <<<PHP + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP <?php -namespace This\Is\My\Ns +namespace This\Is\My\Ns class ThisIsMyTest { @@ -259,8 +240,89 @@ class ThisIsMyTest PHP ); + /** @var $scanner FileClassScanner */ + $scanner->getClassName(); + } + + /** + * Checks a case when file with class also contains `class_alias` function for backward compatibility. + */ + public function testFileContainsClassAliasFunction(): void + { + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<'PHP' +<?php + +namespace This\Is\My\Ns; + +use stdClass; + +class ThisIsMyTest +{ + public function doMethod() + { + $className = stdClass::class; + return $className; + } + + public function secondMethod() + { + $this->doMethod(); + } +} + +class_alias(\This\Is\My\Ns\ThisIsMyTest::class, stdClass::class); + +PHP + ); + + /* @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + self::assertEquals('This\Is\My\Ns\ThisIsMyTest', $result); + } + + /** + * Checks a case when file with class also contains `class_exists` function. + */ + public function testFileContainsClassExistsFunction(): void + { + $scanner = $this->getScannerMockObject(); + $scanner->expects(self::once()) + ->method('getFileContents') + ->willReturn(<<<PHP +<?php + +namespace This\Is\My\Ns; + +if (false) { + class ThisIsMyTest {} +} + +class_exists(\This\Is\My\Ns\ThisIsMySecondTest::class); +trigger_error('This class is does not supported'); +PHP + ); + + /* @var $scanner FileClassScanner */ + $result = $scanner->getClassName(); + self::assertEmpty($result); + } + + /** + * Creates file class scanner mock object. + * + * @return MockObject + */ + private function getScannerMockObject(): MockObject + { + $scanner = $this->getMockBuilder(FileClassScanner::class) + ->disableOriginalConstructor() + ->setMethods(['getFileContents']) + ->getMock(); - $scanner->getClassNames(); + return $scanner; } }