From 181507c8ff61f03c2ae27971f5ad30775d1e7f8c Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Wed, 21 Apr 2021 19:19:25 +0300 Subject: [PATCH 01/21] Do not trigger url rewrites re-generation for all store views --- .../CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php index 50875b1a418d0..52c9babeb0477 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php @@ -92,6 +92,7 @@ public function afterSave( AbstractModel $group ) { if (!$group->isObjectNew() + && $group->getStoreIds() && ($group->dataHasChangedFor('website_id') || $group->dataHasChangedFor('root_category_id')) ) { From 43d6603a99a8a0869e5c1aa37a3b4985e2697a63 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Sat, 24 Apr 2021 00:34:06 +0300 Subject: [PATCH 02/21] Do not trigger url rewrites re-generation for all store views Fix unit tests --- .../Model/Category/Plugin/Store/GroupTest.php | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php index 342826d9bfe9c..d39ca17979f27 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php @@ -88,9 +88,6 @@ protected function setUp(): void ->disableOriginalConstructor() ->setMethods(['isObjectNew', 'dataHasChangedFor', 'getStoreIds']) ->getMockForAbstractClass(); - $this->abstractModelMock->expects($this->any()) - ->method('getStoreIds') - ->willReturn([]); $this->subjectMock = $this->getMockBuilder(Group::class) ->disableOriginalConstructor() ->getMock(); @@ -138,6 +135,9 @@ public function testAfterSave() $this->abstractModelMock->expects($this->once()) ->method('isObjectNew') ->willReturn(false); + $this->abstractModelMock->expects($this->any()) + ->method('getStoreIds') + ->willReturn(['1']); $this->abstractModelMock->expects($this->once()) ->method('dataHasChangedFor') ->with('website_id') @@ -179,4 +179,34 @@ public function testAfterSave() $this->plugin->afterSave($this->subjectMock, $this->subjectMock, $this->abstractModelMock) ); } + + public function testAfterSaveWithNoStoresAssigned() + { + $this->abstractModelMock->expects($this->once()) + ->method('isObjectNew') + ->willReturn(false); + $this->abstractModelMock->expects($this->any()) + ->method('getStoreIds') + ->willReturn([]); + $this->abstractModelMock->expects($this->any()) + ->method('dataHasChangedFor') + ->with('website_id') + ->willReturn(true); + $this->storeManagerMock->expects($this->never())->method('reinitStores'); + $this->categoryMock->expects($this->never())->method('getCategories'); + $this->categoryFactoryMock->expects($this->never())->method('create'); + $this->productFactoryMock->expects($this->never())->method('create'); + $this->productMock->expects($this->never())->method('getCollection'); + $this->productCollectionMock->expects($this->never())->method('addCategoryIds'); + $this->productCollectionMock->expects($this->never()) ->method('addAttributeToSelect'); + $this->productCollectionMock->expects($this->never())->method('addWebsiteFilter'); + $iterator = new \ArrayIterator([$this->productMock]); + $this->productCollectionMock->expects($this->never())->method('getIterator'); + $this->productUrlRewriteGeneratorMock->expects($this->never())->method('generate'); + + $this->assertSame( + $this->subjectMock, + $this->plugin->afterSave($this->subjectMock, $this->subjectMock, $this->abstractModelMock) + ); + } } From a61277cb287388f050ee93d1d2baa1cc95d3b22c Mon Sep 17 00:00:00 2001 From: engcom-Kilo Date: Fri, 28 May 2021 16:20:23 +0300 Subject: [PATCH 03/21] MC-42160: Static CMS image urls when using a different (sub)domain for custom admin url --- .../Magento/Cms/Helper/Wysiwyg/Images.php | 74 +++++++++++-------- .../Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 62 ++++++++++------ .../Images/GetInsertImageContentTest.php | 28 ++++--- 3 files changed, 101 insertions(+), 63 deletions(-) diff --git a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php index b45d4a04b62b3..8073fe3c00431 100644 --- a/app/code/Magento/Cms/Helper/Wysiwyg/Images.php +++ b/app/code/Magento/Cms/Helper/Wysiwyg/Images.php @@ -3,16 +3,30 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Cms\Helper\Wysiwyg; +use Exception; +use InvalidArgumentException; +use Magento\Backend\Helper\Data; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Exception\ValidatorException; +use Magento\Framework\App\Helper\AbstractHelper; +use Magento\Framework\App\Helper\Context; +use Magento\Framework\Escaper; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\Read; +use Magento\Framework\Filesystem\Directory\Write; +use Magento\Framework\UrlInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Theme\Helper\Storage; /** * Wysiwyg Images Helper. * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Images extends \Magento\Framework\App\Helper\AbstractHelper +class Images extends AbstractHelper { /** * Image directory subpath relative to media directory @@ -23,12 +37,14 @@ class Images extends \Magento\Framework\App\Helper\AbstractHelper /** * Current directory path + * * @var string */ protected $_currentPath; /** * Current directory URL + * * @var string */ protected $_currentUrl; @@ -41,51 +57,51 @@ class Images extends \Magento\Framework\App\Helper\AbstractHelper protected $_storeId; /** - * @var \Magento\Framework\Filesystem\Directory\Write + * @var Write */ protected $_directory; /** * Adminhtml data * - * @var \Magento\Backend\Helper\Data + * @var Data */ protected $_backendData; /** * Store manager * - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $_storeManager; /** * String escaper * - * @var \Magento\Framework\Escaper + * @var Escaper */ protected $escaper; /** - * @var \Magento\Framework\Filesystem\Directory\Read + * @var Read */ private $_readDirectory; /** * Construct * - * @param \Magento\Framework\App\Helper\Context $context - * @param \Magento\Backend\Helper\Data $backendData - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\Escaper $escaper + * @param Context $context + * @param Data $backendData + * @param Filesystem $filesystem + * @param StoreManagerInterface $storeManager + * @param Escaper $escaper */ public function __construct( - \Magento\Framework\App\Helper\Context $context, - \Magento\Backend\Helper\Data $backendData, - \Magento\Framework\Filesystem $filesystem, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Escaper $escaper + Context $context, + Data $backendData, + Filesystem $filesystem, + StoreManagerInterface $storeManager, + Escaper $escaper ) { parent::__construct($context); $this->_backendData = $backendData; @@ -136,7 +152,7 @@ public function getStorageRootSubpath() */ public function getBaseUrl() { - return $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); + return $this->_storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA); } /** @@ -166,19 +182,19 @@ public function convertPathToId($path) * * @param string $id * @return string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ public function convertIdToPath($id) { - if ($id === \Magento\Theme\Helper\Storage::NODE_ROOT) { + if ($id === Storage::NODE_ROOT) { return $this->getStorageRoot(); } else { $path = $this->getStorageRoot() . $this->idDecode($id); try { $this->_readDirectory->getAbsolutePath($path); - } catch (\Exception $e) { - throw new \InvalidArgumentException('Path is invalid'); + } catch (Exception $e) { + throw new InvalidArgumentException('Path is invalid'); } return $path; @@ -192,7 +208,7 @@ public function convertIdToPath($id) */ public function isUsingStaticUrlsAllowed() { - $checkResult = (object) []; + $checkResult = (object)[]; $checkResult->isAllowed = false; $this->_eventManager->dispatch( 'cms_wysiwyg_images_static_urls_allowed', @@ -211,7 +227,7 @@ public function isUsingStaticUrlsAllowed() public function getImageHtmlDeclaration($filename, $renderAsTag = false) { $fileUrl = $this->getCurrentUrl() . $filename; - $mediaUrl = $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); + $mediaUrl = $this->_storeManager->getStore($this->_storeId)->getBaseUrl(UrlInterface::URL_TYPE_MEDIA); $mediaPath = str_replace($mediaUrl, '', $fileUrl); $directive = sprintf('{{media url="%s"}}', $mediaPath); if ($renderAsTag) { @@ -238,7 +254,7 @@ public function getImageHtmlDeclaration($filename, $renderAsTag = false) * Return path of the root directory for startup. Also try to create target directory if it doesn't exist * * @return string - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getCurrentPath() { @@ -268,7 +284,7 @@ public function getCurrentPath() * Create subdirectory if doesn't exist * * @param string $absPath Path of subdirectory to create - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ private function createSubDirIfNotExist(string $absPath) { @@ -276,13 +292,13 @@ private function createSubDirIfNotExist(string $absPath) if (!$this->_directory->isExist($relPath)) { try { $this->_directory->create($relPath); - } catch (\Magento\Framework\Exception\FileSystemException $e) { + } catch (FileSystemException $e) { $message = __( 'Can\'t create %1 as subdirectory of %2, you might have some permission issue.', $relPath, $this->_directory->getAbsolutePath() ); - throw new \Magento\Framework\Exception\LocalizedException($message); + throw new LocalizedException($message); } } } @@ -299,7 +315,7 @@ public function getCurrentUrl() $mediaUrl = $this->_storeManager->getStore( $this->_storeId )->getBaseUrl( - \Magento\Framework\UrlInterface::URL_TYPE_MEDIA + UrlInterface::URL_TYPE_MEDIA ); $this->_currentUrl = rtrim($mediaUrl . $this->_directory->getRelativePath($path), '/') . '/'; } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index 7d3bf7ec1a1ea..e6a87e57a2c9f 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -3,12 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Cms\Helper\Wysiwyg; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\Helper\Context; +use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Filesystem; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; +use stdClass; -class ImagesTest extends \PHPUnit\Framework\TestCase +class ImagesTest extends TestCase { /** * @var ObjectManager @@ -17,19 +25,17 @@ class ImagesTest extends \PHPUnit\Framework\TestCase protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); } public function testGetStorageRoot() { - /** @var \Magento\Framework\Filesystem $filesystem */ - $filesystem = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\Filesystem::class - ); + /** @var Filesystem $filesystem */ + $filesystem = Bootstrap::getObjectManager()->get(Filesystem::class); $mediaPath = $filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath(); - /** @var \Magento\Cms\Helper\Wysiwyg\Images $helper */ + /** @var Images $helper */ $helper = $this->objectManager->create( - \Magento\Cms\Helper\Wysiwyg\Images::class + Images::class ); $this->assertStringStartsWith($mediaPath, $helper->getStorageRoot()); } @@ -39,10 +45,9 @@ public function testGetStorageRoot() */ public function testGetCurrentUrl() { - /** @var \Magento\Cms\Helper\Wysiwyg\Images $helper */ - $helper = $this->objectManager->create( - \Magento\Cms\Helper\Wysiwyg\Images::class - ); + /** @var Images $helper */ + $helper = $this->objectManager->create(Images::class); + $this->assertStringStartsWith('http://example.com/', $helper->getCurrentUrl()); } @@ -74,6 +79,20 @@ public function testGetImageHtmlDeclaration( } } + /** + * Verify image html declaration renders correctly with custom admin url. + * + * @magentoConfigFixture default/admin/url/use_custom 1 + * @magentoConfigFixture admin_store web/unsecure/base_url http://example-admin.com/ + */ + public function testGetImageHtmlDeclarationCustomBackendUrl() + { + $helper = $this->generateHelper(false, 0); + $actualResult = $helper->getImageHtmlDeclaration('wysiwyg/hello.png', true); + + $this->assertEquals('', $actualResult); + } + /** * Data provider for testGetImageHtmlDeclaration * @@ -94,7 +113,7 @@ function ($actualResult) { ); $this->assertStringContainsString($expectedResult, parse_url($actualResult, PHP_URL_PATH)); - } + }, ], [true, 'wysiwyg/hello.png', false, 'http://example.com/media/wysiwyg/hello.png'], [false, 'wysiwyg/hello.png', true, ''], @@ -105,24 +124,23 @@ function ($actualResult) { * Generate instance of Images Helper * * @param bool $isStaticUrlsAllowed - mock is created to override value of isUsingStaticUrlsAllowed method in class - * @return \Magento\Cms\Helper\Wysiwyg\Images + * @param int $storeId + * @return Images * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ - private function generateHelper($isStaticUrlsAllowed = false) + private function generateHelper($isStaticUrlsAllowed = false, int $storeId = 1) { - $storeId = 1; - - $eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); + $eventManagerMock = $this->createMock(ManagerInterface::class); - $contextMock = $this->objectManager->create(\Magento\Framework\App\Helper\Context::class, [ + $contextMock = $this->objectManager->create(Context::class, [ 'eventManager' => $eventManagerMock, ]); - $helper = $this->objectManager->create(\Magento\Cms\Helper\Wysiwyg\Images::class, [ - 'context' => $contextMock + $helper = $this->objectManager->create(Images::class, [ + 'context' => $contextMock, ]); - $checkResult = new \stdClass(); + $checkResult = new stdClass(); $checkResult->isAllowed = false; $eventManagerMock->expects($this->any()) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/GetInsertImageContentTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/GetInsertImageContentTest.php index 7ce695cb476fe..ca0f26dee54c0 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/GetInsertImageContentTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/Wysiwyg/Images/GetInsertImageContentTest.php @@ -11,6 +11,7 @@ use Magento\Backend\Model\UrlInterface; use Magento\Cms\Helper\Wysiwyg\Images as ImagesHelper; use Magento\Framework\Url\EncoderInterface; +use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; use PHPUnit\Framework\TestCase; @@ -51,25 +52,28 @@ protected function setUp(): void * Test for GetInsertImageContent::execute * * @dataProvider imageDataProvider + * @magentoDataFixture Magento/Store/_files/core_fixturestore.php * @param string $filename * @param bool $forceStaticPath * @param bool $renderAsTag - * @param int|null $storeId + * @param string|null $storeCode * @param string $expectedResult */ public function testExecute( string $filename, bool $forceStaticPath, bool $renderAsTag, - ?int $storeId, + ?string $storeCode, string $expectedResult ): void { + $storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class); + $storeId = $storeCode ? (int)$storeManager->getStore($storeCode)->getId() : null; if (!$forceStaticPath && !$renderAsTag && !$this->imagesHelper->isUsingStaticUrlsAllowed()) { $expectedResult = $this->url->getUrl( 'cms/wysiwyg/directive', [ '___directive' => $this->urlEncoder->encode($expectedResult), - '_escape_params' => false + '_escape_params' => false, ] ); } @@ -97,36 +101,36 @@ public function imageDataProvider(): array 'test-image.jpg', false, true, - 1, - '' + 'default', + '', ], [ 'catalog/category/test-image.jpg', true, false, - 1, - '/media/catalog/category/test-image.jpg' + 'default', + '/media/catalog/category/test-image.jpg', ], [ 'test-image.jpg', false, false, - 1, - '{{media url="test-image.jpg"}}' + 'default', + '{{media url="test-image.jpg"}}', ], [ '/test-image.jpg', false, true, - 2, - '' + 'fixturestore', + '', ], [ 'test-image.jpg', false, true, null, - '' + '', ], ]; } From 092fe02142459d1ed16b7674fd5bc255703dc903 Mon Sep 17 00:00:00 2001 From: Dmitry Tsymbal Date: Fri, 4 Jun 2021 16:06:17 +0300 Subject: [PATCH 04/21] Create Attribute Rating Test --- .../AdminClickSaveRatingButtonActionGroup.xml | 15 +++++++ ...nFillNewRatingAttributeFormActionGroup.xml | 22 ++++++++++ .../AdminRatingDeleteAttributeActionGroup.xml | 16 +++++++ ...OpenRatingAttributeFromGridActionGroup.xml | 15 +++++++ ...SearchRatingAttributeOnGridActionGroup.xml | 20 +++++++++ ...tAdminRatingAttributeInGridActionGroup.xml | 18 ++++++++ .../Section/AdminEditAndNewRatingSection.xml | 3 ++ .../Mftf/Section/AdminRatingGridSection.xml | 18 ++++++++ .../AdminRatingsAddNewRatingAttributeTest.xml | 44 +++++++++++++++++++ 9 files changed, 171 insertions(+) create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminClickSaveRatingButtonActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFillNewRatingAttributeFormActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingDeleteAttributeActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingOpenRatingAttributeFromGridActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminSearchRatingAttributeOnGridActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AssertAdminRatingAttributeInGridActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/Section/AdminRatingGridSection.xml create mode 100644 app/code/Magento/Review/Test/Mftf/Test/AdminRatingsAddNewRatingAttributeTest.xml diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminClickSaveRatingButtonActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminClickSaveRatingButtonActionGroup.xml new file mode 100644 index 0000000000000..68f6fa4980d97 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminClickSaveRatingButtonActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFillNewRatingAttributeFormActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFillNewRatingAttributeFormActionGroup.xml new file mode 100644 index 0000000000000..c0942f67a3c63 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFillNewRatingAttributeFormActionGroup.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingDeleteAttributeActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingDeleteAttributeActionGroup.xml new file mode 100644 index 0000000000000..dfe7bb84039f1 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingDeleteAttributeActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingOpenRatingAttributeFromGridActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingOpenRatingAttributeFromGridActionGroup.xml new file mode 100644 index 0000000000000..bd94ef4b81822 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminRatingOpenRatingAttributeFromGridActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminSearchRatingAttributeOnGridActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminSearchRatingAttributeOnGridActionGroup.xml new file mode 100644 index 0000000000000..b45547b43bb3e --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminSearchRatingAttributeOnGridActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AssertAdminRatingAttributeInGridActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AssertAdminRatingAttributeInGridActionGroup.xml new file mode 100644 index 0000000000000..55794d89eb70b --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AssertAdminRatingAttributeInGridActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/app/code/Magento/Review/Test/Mftf/Section/AdminEditAndNewRatingSection.xml b/app/code/Magento/Review/Test/Mftf/Section/AdminEditAndNewRatingSection.xml index 59dd3d2004790..9847ead2f8226 100644 --- a/app/code/Magento/Review/Test/Mftf/Section/AdminEditAndNewRatingSection.xml +++ b/app/code/Magento/Review/Test/Mftf/Section/AdminEditAndNewRatingSection.xml @@ -11,5 +11,8 @@
+ + +
diff --git a/app/code/Magento/Review/Test/Mftf/Section/AdminRatingGridSection.xml b/app/code/Magento/Review/Test/Mftf/Section/AdminRatingGridSection.xml new file mode 100644 index 0000000000000..e5ae494e7718c --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/Section/AdminRatingGridSection.xml @@ -0,0 +1,18 @@ + + + + +
+ + + + + +
+
diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminRatingsAddNewRatingAttributeTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminRatingsAddNewRatingAttributeTest.xml new file mode 100644 index 0000000000000..7e5b17f6e4738 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminRatingsAddNewRatingAttributeTest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + <description value="Admin should be able add new rating attribute"/> + <severity value="MINOR"/> + <group value="review"/> + </annotations> + <before> + <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminRatingOpenRatingAttributeFromGridActionGroup" stepKey="openAttribute"/> + <actionGroup ref="AdminRatingDeleteAttributeActionGroup" stepKey="deleteCreatedRatingAttribute"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + <actionGroup ref="AdminNavigateToNewRatingFormActionGroup" stepKey="navigateToNewRatingPage"/> + <actionGroup ref="AdminFillNewRatingAttributeFormActionGroup" stepKey="fillRatingForm"> + <argument name="default_Value" value="Test Rating"/> + <argument name="store" value="Default Store View"/> + </actionGroup> + <actionGroup ref="AdminClickSaveRatingButtonActionGroup" stepKey="saveRatingAttribute"/> + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="assertSuccessMessage"> + <argument name="message" value="You saved the rating."/> + </actionGroup> + <actionGroup ref="AdminSearchRatingAttributeOnGridActionGroup" stepKey="searchCreatedRatingOnGrid"> + <argument name="rating" value="Test Rating"/> + </actionGroup> + <actionGroup ref="AssertAdminRatingAttributeInGridActionGroup" stepKey="assertRatingAttributeInGrid"> + <argument name="rating" value="Test Rating"/> + </actionGroup> + </test> +</tests> From c6f29a8392003c2ab3257467b314213aea989b83 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 4 Aug 2021 17:27:55 +0300 Subject: [PATCH 05/21] refactored StorefrontOrderPagerIsAbsentTest --- .../Test/StorefrontOrderPagerIsAbsentTest.xml | 207 ++++++++++-------- 1 file changed, 118 insertions(+), 89 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml index 752b2a5b7d824..d4d54b601318d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontOrderPagerIsAbsentTest.xml @@ -19,8 +19,8 @@ <group value="mtf_migrated"/> </annotations> <before> - <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> - <!-- 20 products created and category --> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="LoginAsAdmin"/> + <createData entity="_defaultCategory" stepKey="createCategory"/> <createData entity="SimpleProduct" stepKey="createProduct01"> <requiredEntity createDataKey="createCategory"/> @@ -83,12 +83,10 @@ <requiredEntity createDataKey="createCategory"/> </createData> - <!-- Customer is created --> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> </before> <after> - <!-- Delete category and products --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct01" stepKey="deleteProduct1"/> <deleteData createDataKey="createProduct02" stepKey="deleteProduct2"/> @@ -111,103 +109,134 @@ <deleteData createDataKey="createProduct19" stepKey="deleteProduct19"/> <deleteData createDataKey="createProduct20" stepKey="deleteProduct20"/> - <!-- Delete Customer --> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - - <!-- Login to Storefront as Customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> <argument name="Customer" value="$$createCustomer$$" /> </actionGroup> + + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="onCategoryPage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="scrollToLimiter"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectLimitOnPage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoadProducts"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="scrollToTopOfPage"/> - <!-- Customer placed the order with 20 products --> - <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.custom_attributes[url_key]$$)}}" stepKey="onCategoryPage"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <scrollTo selector="{{StorefrontCategoryMainSection.perPage}}" stepKey="scrollToLimiter"/> - <selectOption userInput="36" selector="{{StorefrontCategoryMainSection.perPage}}" stepKey="selectLimitOnPage"/> - <waitForPageLoad stepKey="waitForLoadProducts"/> - <scrollToTopOfPage stepKey="scrollToTopOfPage"/> + <createData entity="CustomerCart" stepKey="createCustomerCart"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct1"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct01"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct2"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct02"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct3"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct03"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct4"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct04"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct5"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct05"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct6"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct06"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct7"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct07"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct8"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct08"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct9"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct09"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct10"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct10"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct11"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct11"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct12"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct12"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct13"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct13"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct14"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct14"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct15"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct15"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct16"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct16"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct17"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct17"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct18"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct18"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct19"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct19"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addProduct20"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct20"/> + </createData> + + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="onCheckout"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="see20Products"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickNextButton"/> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct1"> - <argument name="productName" value="$$createProduct01.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct2"> - <argument name="productName" value="$$createProduct02.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct3"> - <argument name="productName" value="$$createProduct03.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct4"> - <argument name="productName" value="$$createProduct04.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct5"> - <argument name="productName" value="$$createProduct05.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct6"> - <argument name="productName" value="$$createProduct06.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct7"> - <argument name="productName" value="$$createProduct07.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct8"> - <argument name="productName" value="$$createProduct08.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct9"> - <argument name="productName" value="$$createProduct09.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct10"> - <argument name="productName" value="$$createProduct10.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct11"> - <argument name="productName" value="$$createProduct11.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct12"> - <argument name="productName" value="$$createProduct12.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct13"> - <argument name="productName" value="$$createProduct13.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct14"> - <argument name="productName" value="$$createProduct14.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct15"> - <argument name="productName" value="$$createProduct15.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct16"> - <argument name="productName" value="$$createProduct16.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct17"> - <argument name="productName" value="$$createProduct17.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct18"> - <argument name="productName" value="$$createProduct18.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct19"> - <argument name="productName" value="$$createProduct19.name$$"/> - </actionGroup> - <actionGroup ref="StorefrontAddProductToCartFromCategoryActionGroup" stepKey="addProduct20"> - <argument name="productName" value="$$createProduct20.name$$"/> - </actionGroup> + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddress"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> - <!-- Place Order --> - <actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="onCheckout"/> - <see userInput="20" selector="{{CheckoutOrderSummarySection.itemsQtyInCart}}" stepKey="see20Products"/> - <actionGroup ref="StorefrontCheckoutClickNextOnShippingStepActionGroup" stepKey="clickNextButton"/> - <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="placeOrder"/> - <waitForPageLoad stepKey="waitForSuccess"/> - <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <updateData createDataKey="createCustomerCart" entity="CustomerOrderPaymentMethod" stepKey="placeOrder"> + <requiredEntity createDataKey="createCustomerCart"/> + </updateData> - <!-- Go to My Account > My Orders page --> - <actionGroup ref="StorefrontOpenMyAccountPageActionGroup" stepKey="onMyAccount"/> - <click selector="{{StorefrontCustomerSidebarSection.sidebarTab('My Orders')}}" stepKey="clickOnMyOrders"/> - <waitForPageLoad stepKey="waitForOrdersLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSuccess"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="grabOrderNumber"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="onMyAccount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnMyOrders"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForOrdersLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOrderView"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForOrderPageLoad"/> - <!-- Click 'View Order' link on order from preconditions --> - <click selector="{{StorefrontCustomerOrdersGridSection.orderView({$grabOrderNumber})}}" stepKey="clickOrderView"/> - <waitForPageLoad stepKey="waitForOrderPageLoad"/> + <getData entity="GetOrderData" stepKey="getOrderData"> + <requiredEntity createDataKey="createCustomerCart"/> + </getData> + + <actionGroup ref="StorefrontGoToCustomerOrderDetailsPageActionGroup" stepKey="openOrderDetailPage"> + <argument name="orderId" value="$createCustomerCart.return$"/> + <argument name="orderNumber" value="$getOrderData.increment_id$"/> + </actionGroup> - <!-- Assert: Order items pager hidden on frontend --> <dontSeeElement selector="{{StorefrontCustomerOrderViewSection.pager}}" stepKey="assertPagerIsAbsent"/> </test> </tests> From d0f220111548123a7a77102cc516b1043d54d905 Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:51:16 +0200 Subject: [PATCH 06/21] Fix "area code is not set" in all commands that depend on Payment/Helper/Data --- app/code/Magento/Payment/Helper/Data.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index 782ef39082438..a4e324d03f004 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -31,12 +31,6 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper */ protected $_paymentConfig; - /** - * Layout - * - * @var \Magento\Framework\View\LayoutInterface - */ - protected $_layout; /** * Factory for payment method models @@ -76,7 +70,6 @@ public function __construct( \Magento\Framework\App\Config\Initial $initialConfig ) { parent::__construct($context); - $this->_layout = $layoutFactory->create(); $this->_methodFactory = $paymentMethodFactory; $this->_appEmulation = $appEmulation; $this->_paymentConfig = $paymentConfig; @@ -183,7 +176,7 @@ public function getMethodFormBlock(MethodInterface $method, LayoutInterface $lay */ public function getInfoBlock(InfoInterface $info, LayoutInterface $layout = null) { - $layout = $layout ?: $this->_layout; + $layout = $layout ?: $layoutFactory->create(); $blockType = $info->getMethodInstance()->getInfoBlockType(); $block = $layout->createBlock($blockType); $block->setInfo($info); From b4a7f92f65327be2b2036a9ed3444f98e3dfafc3 Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:03:45 +0200 Subject: [PATCH 07/21] Fix --- app/code/Magento/Payment/Helper/Data.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index a4e324d03f004..b9760c732e87a 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -31,6 +31,10 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper */ protected $_paymentConfig; + /** + * @var \Magento\Framework\View\LayoutFactory + */ + protected $_layoutFactory; /** * Factory for payment method models @@ -70,6 +74,7 @@ public function __construct( \Magento\Framework\App\Config\Initial $initialConfig ) { parent::__construct($context); + $this->_layoutFactory = $_layoutFactory; $this->_methodFactory = $paymentMethodFactory; $this->_appEmulation = $appEmulation; $this->_paymentConfig = $paymentConfig; @@ -176,7 +181,7 @@ public function getMethodFormBlock(MethodInterface $method, LayoutInterface $lay */ public function getInfoBlock(InfoInterface $info, LayoutInterface $layout = null) { - $layout = $layout ?: $layoutFactory->create(); + $layout = $layout ?: $this->_layoutFactory->create(); $blockType = $info->getMethodInstance()->getInfoBlockType(); $block = $layout->createBlock($blockType); $block->setInfo($info); From ee828bcba8865d6131ec13f699ab6e6c6800a26a Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:21:33 +0200 Subject: [PATCH 08/21] Fix #2 i dont know how to squash commits :( --- app/code/Magento/Payment/Helper/Data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index b9760c732e87a..46a06040830e9 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -74,7 +74,7 @@ public function __construct( \Magento\Framework\App\Config\Initial $initialConfig ) { parent::__construct($context); - $this->_layoutFactory = $_layoutFactory; + $this->_layoutFactory = $layoutFactory; $this->_methodFactory = $paymentMethodFactory; $this->_appEmulation = $appEmulation; $this->_paymentConfig = $paymentConfig; From 1a3a59f9fb36d903608e02f21d9058a4b28fc3b7 Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:28:24 +0200 Subject: [PATCH 09/21] restore $layout property and make it deprecated --- app/code/Magento/Payment/Helper/Data.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index 46a06040830e9..95fd6f688efc6 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -32,6 +32,14 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper protected $_paymentConfig; /** + * Layout + * @deprecated + * @var \Magento\Framework\View\LayoutInterface + */ + protected $_layout; + + /** + * LayoutFactory * @var \Magento\Framework\View\LayoutFactory */ protected $_layoutFactory; From 63e87da5a85be44240cd3b14bfd7f0046f988253 Mon Sep 17 00:00:00 2001 From: Marvin Hinz <35603466+marvinhinz@users.noreply.github.com> Date: Fri, 13 Aug 2021 13:29:20 +0200 Subject: [PATCH 10/21] Change new property visibility to private --- app/code/Magento/Payment/Helper/Data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index 95fd6f688efc6..acfbfe0f9ac56 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -42,7 +42,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper * LayoutFactory * @var \Magento\Framework\View\LayoutFactory */ - protected $_layoutFactory; + private $_layoutFactory; /** * Factory for payment method models From 055d9fc3702095a356806f23451ae084cf724fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=C3=A9nse?= <reense@icloud.com> Date: Mon, 23 Aug 2021 12:15:57 +0200 Subject: [PATCH 11/21] Replaced PHP8-only str_contains method. --- .../Framework/Filesystem/Directory/DenyListPathValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php index 60a2a5ca14298..cae235ec90ea7 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php @@ -71,7 +71,7 @@ public function validate( foreach ($this->fileDenyList as $file) { $baseName = pathinfo($actualPath, PATHINFO_BASENAME); - if (str_contains($baseName, $file) || preg_match('#' . "\." . $file . '#', $fullPath)) { + if (stripos($baseName, $file) !== false || preg_match('#' . "\." . $file . '#', $fullPath)) { throw new ValidatorException( new Phrase('"%1" is not a valid file path', [$path]) ); From 2c2454a299c12dc3e1554548b430bdd91bf413ba Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Wed, 25 Aug 2021 12:38:01 +0300 Subject: [PATCH 12/21] Fix unit tests Signed-off-by: Denis Kopylov <dkopylov@magenius.team> --- app/code/Magento/Payment/Helper/Data.php | 89 +++++++++++-------- .../Payment/Test/Unit/Helper/DataTest.php | 11 ++- 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index acfbfe0f9ac56..a0089a2b7cde9 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -1,11 +1,24 @@ <?php +declare(strict_types=1); /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Helper; +use Exception; +use Magento\Framework\App\Area; +use Magento\Framework\App\Config\Initial; +use Magento\Framework\App\Helper\AbstractHelper; +use Magento\Framework\App\Helper\Context; +use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\Config; +use Magento\Payment\Model\Method\Factory; +use Magento\Payment\Model\Method\Free; use Magento\Quote\Model\Quote; +use Magento\Store\Model\App\Emulation; +use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\Store; use Magento\Payment\Block\Form; use Magento\Payment\Model\InfoInterface; @@ -14,6 +27,7 @@ use Magento\Framework\View\LayoutFactory; use Magento\Payment\Model\Method\AbstractMethod; use Magento\Payment\Model\MethodInterface; +use UnexpectedValueException; /** * Payment module base helper @@ -22,67 +36,68 @@ * @api * @since 100.0.2 */ -class Data extends \Magento\Framework\App\Helper\AbstractHelper +class Data extends AbstractHelper { const XML_PATH_PAYMENT_METHODS = 'payment'; /** - * @var \Magento\Payment\Model\Config + * @var Config */ protected $_paymentConfig; /** * Layout * @deprecated - * @var \Magento\Framework\View\LayoutInterface + * @var LayoutInterface */ protected $_layout; /** * LayoutFactory - * @var \Magento\Framework\View\LayoutFactory + * + * @var LayoutFactory */ - private $_layoutFactory; + private $layoutFactory; /** * Factory for payment method models * - * @var \Magento\Payment\Model\Method\Factory + * @var Factory */ protected $_methodFactory; /** * App emulation model * - * @var \Magento\Store\Model\App\Emulation + * @var Emulation */ protected $_appEmulation; /** - * @var \Magento\Framework\App\Config\Initial + * @var Initial */ protected $_initialConfig; /** * Construct * - * @param \Magento\Framework\App\Helper\Context $context + * @param Context $context * @param LayoutFactory $layoutFactory - * @param \Magento\Payment\Model\Method\Factory $paymentMethodFactory - * @param \Magento\Store\Model\App\Emulation $appEmulation - * @param \Magento\Payment\Model\Config $paymentConfig - * @param \Magento\Framework\App\Config\Initial $initialConfig + * @param Factory $paymentMethodFactory + * @param Emulation $appEmulation + * @param Config $paymentConfig + * @param Initial $initialConfig */ public function __construct( - \Magento\Framework\App\Helper\Context $context, + Context $context, LayoutFactory $layoutFactory, - \Magento\Payment\Model\Method\Factory $paymentMethodFactory, - \Magento\Store\Model\App\Emulation $appEmulation, - \Magento\Payment\Model\Config $paymentConfig, - \Magento\Framework\App\Config\Initial $initialConfig + Factory $paymentMethodFactory, + Emulation $appEmulation, + Config $paymentConfig, + Initial $initialConfig ) { parent::__construct($context); - $this->_layoutFactory = $layoutFactory; + $this->layoutFactory = $layoutFactory; $this->_methodFactory = $paymentMethodFactory; $this->_appEmulation = $appEmulation; $this->_paymentConfig = $paymentConfig; @@ -105,18 +120,18 @@ protected function getMethodModelConfigName($code) * * @param string $code * - * @throws \Magento\Framework\Exception\LocalizedException * @return MethodInterface + * @throws LocalizedException */ public function getMethodInstance($code) { $class = $this->scopeConfig->getValue( $this->getMethodModelConfigName($code), - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ); if (!$class) { - throw new \UnexpectedValueException('Payment model name is not provided in config!'); + throw new UnexpectedValueException('Payment model name is not provided in config!'); } return $this->_methodFactory->create($class); @@ -139,7 +154,7 @@ public function getStoreMethods($store = null, $quote = null) foreach (array_keys($methods) as $code) { $model = $this->scopeConfig->getValue( $this->getMethodModelConfigName($code), - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + ScopeInterface::SCOPE_STORE, $store ); if (!$model) { @@ -184,12 +199,12 @@ public function getMethodFormBlock(MethodInterface $method, LayoutInterface $lay * Retrieve payment information block * * @param InfoInterface $info - * @param \Magento\Framework\View\LayoutInterface $layout + * @param LayoutInterface $layout * @return Template */ public function getInfoBlock(InfoInterface $info, LayoutInterface $layout = null) { - $layout = $layout ?: $this->_layoutFactory->create(); + $layout = $layout ?: $this->layoutFactory->create(); $blockType = $info->getMethodInstance()->getInfoBlockType(); $block = $layout->createBlock($blockType); $block->setInfo($info); @@ -202,21 +217,21 @@ public function getInfoBlock(InfoInterface $info, LayoutInterface $layout = null * @param InfoInterface $info * @param int $storeId * @return string - * @throws \Exception + * @throws Exception */ public function getInfoBlockHtml(InfoInterface $info, $storeId) { - $this->_appEmulation->startEnvironmentEmulation($storeId, \Magento\Framework\App\Area::AREA_FRONTEND, true); + $this->_appEmulation->startEnvironmentEmulation($storeId, Area::AREA_FRONTEND, true); try { // Retrieve specified view block from appropriate design package (depends on emulated store) $paymentBlock = $this->getInfoBlock($info); - $paymentBlock->setArea(\Magento\Framework\App\Area::AREA_FRONTEND) + $paymentBlock->setArea(Area::AREA_FRONTEND) ->setIsSecureMode(true); $paymentBlock->getMethod() ->setStore($storeId); $paymentBlockHtml = $paymentBlock->toHtml(); - } catch (\Exception $exception) { + } catch (Exception $exception) { $this->_appEmulation->stopEnvironmentEmulation(); throw $exception; } @@ -319,8 +334,8 @@ public function getPaymentMethodList($sorted = true, $asLabelValue = false, $wit public function isZeroSubTotal($store = null) { return $this->scopeConfig->getValue( - \Magento\Payment\Model\Method\Free::XML_PATH_PAYMENT_FREE_ACTIVE, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + Free::XML_PATH_PAYMENT_FREE_ACTIVE, + ScopeInterface::SCOPE_STORE, $store ); } @@ -334,8 +349,8 @@ public function isZeroSubTotal($store = null) public function getZeroSubTotalOrderStatus($store = null) { return $this->scopeConfig->getValue( - \Magento\Payment\Model\Method\Free::XML_PATH_PAYMENT_FREE_ORDER_STATUS, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + Free::XML_PATH_PAYMENT_FREE_ORDER_STATUS, + ScopeInterface::SCOPE_STORE, $store ); } @@ -349,8 +364,8 @@ public function getZeroSubTotalOrderStatus($store = null) public function getZeroSubTotalPaymentAutomaticInvoice($store = null) { return $this->scopeConfig->getValue( - \Magento\Payment\Model\Method\Free::XML_PATH_PAYMENT_FREE_PAYMENT_ACTION, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + Free::XML_PATH_PAYMENT_FREE_PAYMENT_ACTION, + ScopeInterface::SCOPE_STORE, $store ); } @@ -365,9 +380,9 @@ public function getZeroSubTotalPaymentAutomaticInvoice($store = null) private function getMethodStoreTitle(string $code, ?int $storeId = null): string { $configPath = sprintf('%s/%s/title', self::XML_PATH_PAYMENT_METHODS, $code); - return (string) $this->scopeConfig->getValue( + return (string)$this->scopeConfig->getValue( $configPath, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + ScopeInterface::SCOPE_STORE, $storeId ); } diff --git a/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php b/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php index 3130aeeaffcb4..8364ecedef3d8 100644 --- a/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php @@ -12,6 +12,7 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\TestFramework\Unit\Matcher\MethodInvokedAtIndex; use Magento\Framework\View\Element\BlockInterface; +use Magento\Framework\View\LayoutFactory; use Magento\Framework\View\LayoutInterface; use Magento\Payment\Helper\Data; use Magento\Payment\Model\Info; @@ -44,6 +45,11 @@ class DataTest extends TestCase */ private $appEmulation; + /** + * @var LayoutFactory|MockObject + */ + private $layoutFactoryMock; + protected function setUp(): void { $objectManagerHelper = new ObjectManager($this); @@ -53,8 +59,7 @@ protected function setUp(): void $context = $arguments['context']; $this->scopeConfig = $context->getScopeConfig(); $this->layoutMock = $this->getMockForAbstractClass(LayoutInterface::class); - $layoutFactoryMock = $arguments['layoutFactory']; - $layoutFactoryMock->expects($this->once())->method('create')->willReturn($this->layoutMock); + $this->layoutFactoryMock = $arguments['layoutFactory']; $this->methodFactory = $arguments['paymentMethodFactory']; $this->appEmulation = $arguments['appEmulation']; @@ -214,6 +219,7 @@ public function testGetInfoBlock() $this->layoutMock->expects($this->once())->method('createBlock') ->with($blockType) ->willReturn($blockMock); + $this->layoutFactoryMock->expects($this->once())->method('create')->willReturn($this->layoutMock); $blockMock->expects($this->once())->method('setInfo')->with($infoMock); $this->assertSame($blockMock, $this->helper->getInfoBlock($infoMock)); @@ -242,6 +248,7 @@ public function testGetInfoBlockHtml() $this->layoutMock->expects($this->once())->method('createBlock') ->with($blockType) ->willReturn($paymentBlockMock); + $this->layoutFactoryMock->expects($this->once())->method('create')->willReturn($this->layoutMock); $paymentBlockMock->expects($this->once())->method('setInfo')->with($infoMock); $paymentBlockMock->expects($this->once())->method('setArea') ->with(Area::AREA_FRONTEND) From 5888eea95fb19c980d604c98886a41077cf5c75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=C3=A9nse?= <reense@icloud.com> Date: Thu, 26 Aug 2021 12:05:24 +0200 Subject: [PATCH 13/21] Check if needle is empty before using strpos. --- .../Framework/Filesystem/Directory/DenyListPathValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php index cae235ec90ea7..03622ad9dad7a 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php @@ -71,7 +71,7 @@ public function validate( foreach ($this->fileDenyList as $file) { $baseName = pathinfo($actualPath, PATHINFO_BASENAME); - if (stripos($baseName, $file) !== false || preg_match('#' . "\." . $file . '#', $fullPath)) { + if ('' === $needle || false !== strpos($haystack, $needle) || preg_match('#' . "\." . $file . '#', $fullPath)) { throw new ValidatorException( new Phrase('"%1" is not a valid file path', [$path]) ); From cda98b598210c3e31ae6f792488a089f300b1c0b Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Thu, 26 Aug 2021 13:34:14 +0300 Subject: [PATCH 14/21] Replaced PHP8-only str_contains method Fix after code review --- .../Framework/Filesystem/Directory/DenyListPathValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php index 03622ad9dad7a..05beedc02730d 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php @@ -71,7 +71,7 @@ public function validate( foreach ($this->fileDenyList as $file) { $baseName = pathinfo($actualPath, PATHINFO_BASENAME); - if ('' === $needle || false !== strpos($haystack, $needle) || preg_match('#' . "\." . $file . '#', $fullPath)) { + if ('' === $file || false !== strpos($baseName, $file) || preg_match('#' . "\." . $file . '#', $fullPath)) { throw new ValidatorException( new Phrase('"%1" is not a valid file path', [$path]) ); From b72097df62a6db2b204a6c9fe4f7647a3eb80832 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 7 Sep 2021 16:24:08 +0300 Subject: [PATCH 15/21] Replaced PHP8-only str_contains method Update patch to be equal to the hotfix in https://support.magento.com/hc/en-us/articles/4408021533069-Adobe-Commerce-upgrade-2-4-3-2-3-7-p1-PHP-Fatal-error-Hotfix --- .../Framework/Filesystem/Directory/DenyListPathValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php index 05beedc02730d..fe49a37ba234e 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/DenyListPathValidator.php @@ -71,7 +71,7 @@ public function validate( foreach ($this->fileDenyList as $file) { $baseName = pathinfo($actualPath, PATHINFO_BASENAME); - if ('' === $file || false !== strpos($baseName, $file) || preg_match('#' . "\." . $file . '#', $fullPath)) { + if (strpos($baseName, $file) !== false || preg_match('#' . "\." . $file . '#', $fullPath)) { throw new ValidatorException( new Phrase('"%1" is not a valid file path', [$path]) ); From dbf4724680659bfbc248a395d74f7474f1800c1b Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 20 Sep 2021 17:43:15 +0300 Subject: [PATCH 16/21] removed excessive order grid filtering --- ...ckoutAsCustomerUsingDefaultAddressTest.xml | 12 ++++++----- ...eCheckoutAsCustomerUsingNewAddressTest.xml | 13 ++++++++---- ...utAsCustomerUsingNonDefaultAddressTest.xml | 10 +++++---- .../OnePageCheckoutUsingSignInLinkTest.xml | 9 +++++--- ...OnePageCheckoutWithAllProductTypesTest.xml | 9 +++++--- ...OnLoginWhenGuestCheckoutIsDisabledTest.xml | 17 +++++++-------- ...StorefrontOpenOrderViewPageActionGroup.xml | 21 +++++++++++++++++++ ...dminCheckingCreditMemoUpdateTotalsTest.xml | 15 +++++++------ ...editMemoForOrderWithCashOnDeliveryTest.xml | 15 ++++++------- ...ifyOrderShipmentForDecimalQuantityTest.xml | 9 +++++--- .../Test/AdminCheckCreditMemoTotalsTest.xml | 2 +- 11 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenOrderViewPageActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml index 3b43ecfa6e8be..8b1a1b2a62eb6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml @@ -81,16 +81,18 @@ <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/> <seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <!-- Login as admin --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <!-- Open created order in backend --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$grabOrderNumber"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="filterOrdersGridById"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> - + <comment userInput="Comment is added to preserve Backward Compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve Backward Compatibility" stepKey="filterOrderGridById"/> + <!-- Assert order total --> <scrollTo selector="{{AdminOrderTotalSection.grandTotal}}" stepKey="scrollToOrderTotalSection"/> <see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$565.00" stepKey="checkOrderTotalInBackend"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml index a508df5aad029..7b6b07f467fbb 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNewAddressTest.xml @@ -90,15 +90,20 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForCheckoutPaymentSectionPageLoad"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="orderIsSuccessfullyPlaced"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <!-- Login as admin --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + + <!--Step11. Go to admin Order page for newly created order--> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$grabOrderId"/> + </actionGroup> <!-- Open created order in backend --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$grabOrderNumber"/> - </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrderGridById"/> <!-- Assert order total --> <scrollTo selector="{{AdminOrderTotalSection.grandTotal}}" stepKey="scrollToOrderTotalSection"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml index 42bec1546e40e..7301cfb48ccc7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml @@ -83,14 +83,16 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForCheckoutPaymentSectionPageLoad"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="orderIsSuccessfullyPlaced"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <!-- Open created order in backend --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$grabOrderNumber"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="filterOrdersGridById"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> + <comment userInput="Comment is added to preserve Backward Compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve Backward Compatibility" stepKey="filterOrderGridById"/> <!-- Assert order total --> <scrollTo selector="{{AdminOrderTotalSection.grandTotal}}" stepKey="scrollToOrderTotalSection"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml index b60a46d348446..dfd4a5deadaf6 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml @@ -75,16 +75,19 @@ <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/> <seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <!-- Login as admin --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <!-- Open created order in backend --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$grabOrderNumber"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrderGridById"/> <!-- Assert that shipping and billing address are the same --> <grabTextFrom selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" stepKey="shippingAddress"/> <grabTextFrom selector="{{AdminShipmentAddressInformationSection.billingAddress}}" stepKey="billingAddress"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index e3aec189bcd57..f2ce8bd0eadd2 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -195,16 +195,19 @@ <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/> <seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced" /> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> <!-- Login as admin --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <!-- Open created order --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$grabOrderNumber"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrderGridById"/> <!-- Assert that addresses on order page the same --> <grabTextFrom selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" stepKey="shippingAddressOrderPage"/> <grabTextFrom selector="{{AdminShipmentAddressInformationSection.billingAddress}}" stepKey="billingAddressOrderPage"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml index bc24b8895d50a..6ed79ab365bc1 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutOnLoginWhenGuestCheckoutIsDisabledTest.xml @@ -76,17 +76,16 @@ <!-- Place order and Assert success message --> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderLink}}" stepKey="orderId"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> - <!-- Open Order Index Page --> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="goToOrders"/> - - <!-- Filter Order using orderId and assert order--> - <actionGroup ref="FilterOrderGridByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$orderId"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> - - <click selector="{{AdminOrdersGridSection.viewLink('$orderId')}}" stepKey="clickOnViewLink"/> - <waitForPageLoad stepKey="waitForOrderPageToLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="goToOrders"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrderGridById"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnViewLink"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForOrderPageToLoad"/> <!-- Ship the order and assert the shipping status --> <actionGroup ref="AdminShipThePendingOrderActionGroup" stepKey="shipTheOrder"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenOrderViewPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenOrderViewPageActionGroup.xml new file mode 100644 index 0000000000000..37c6959ed3527 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontOpenOrderViewPageActionGroup.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="StorefrontOpenOrderViewPageActionGroup"> + <annotations> + <description>Navigates to Storefront Order View page</description> + </annotations> + <arguments> + <argument name="orderId" type="string"/> + </arguments> + <amOnPage url="{{StorefrontCustomerOrderViewPage.url(orderId)}}" stepKey="goToOrderViewPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml index 03dd8b28a624f..b9fb95f7bd36d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml @@ -58,16 +58,15 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="startCreateInvoice"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="submitInvoice"/> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="onOrderPage"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> - <grabTextFrom selector="{{AdminOrdersGridSection.orderIdByIncrementId($createCustomerCart.return$)}}" stepKey="getOrderId"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById"> - <argument name="orderId" value="{$getOrderId}"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$createCustomerCart.return$"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="onOrderPage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clearFilters"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="getOrderId"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrdersGridById"/> - <actionGroup ref="StartToCreateCreditMemoActionGroup" stepKey="startToCreateCreditMemo"> - <argument name="orderId" value="{$getOrderId}"/> - </actionGroup> + <actionGroup ref="AdminStartToCreateCreditMemoFromOrderPageActionGroup" stepKey="startToCreateCreditMemo"/> <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> <actionGroup ref="UpdateCreditMemoTotalsActionGroup" stepKey="updateCreditMemoTotals"/> <actionGroup ref="SubmitCreditMemoActionGroup" stepKey="submitCreditMemo"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoForOrderWithCashOnDeliveryTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoForOrderWithCashOnDeliveryTest.xml index 7709b847b996b..37cba6165e122 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoForOrderWithCashOnDeliveryTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoForOrderWithCashOnDeliveryTest.xml @@ -59,12 +59,14 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="onOrderPage"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> - <grabTextFrom selector="{{AdminOrdersGridSection.orderIdByIncrementId($createCustomerCart.return$)}}" stepKey="grabOrderId"/> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById"> - <argument name="orderId" value="{$grabOrderId}"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openAdminOrderViewPage"> + <argument name="entityId" value="$createCustomerCart.return$"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="onOrderPage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clearFilters"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="grabOrderId"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterOrdersGridById"/> + <actionGroup ref="AdminOpenAndFillCreditMemoRefundActionGroup" stepKey="fillCreditMemoRefund"> <argument name="itemQtyToRefund" value="1"/> @@ -88,9 +90,8 @@ <argument name="Customer" value="$$createCustomer$$"/> </actionGroup> - <actionGroup ref="StorefrontGoToCustomerOrderDetailsPageActionGroup" stepKey="openOrderDetailPage"> + <actionGroup ref="StorefrontOpenOrderViewPageActionGroup" stepKey="openOrderDetailPage"> <argument name="orderId" value="$createCustomerCart.return$"/> - <argument name="orderNumber" value="{$grabOrderId}"/> </actionGroup> <actionGroup ref="StorefrontClickRefundTabCustomerOrderViewActionGroup" stepKey="clickRefund"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml index b086074132e85..a0d74433bd512 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml @@ -31,7 +31,7 @@ <after> <!--Clear Filters--> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="ClearFiltersAfter"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderListingFilters"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clearOrderListingFilters"/> <deleteData createDataKey="createSimpleCategory" stepKey="deletePreReqCategory"/> <deleteData createDataKey="createSimpleProduct" stepKey="deletePreReqSimpleProduct"/> <!--Logout from customer account--> @@ -85,9 +85,12 @@ <!--Step10. Click place order--> <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="placeOrder"/> <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <actionGroup ref="StorefrontClickOrderLinkFromCheckoutSuccessPageActionGroup" stepKey="openOrderViewPage"/> + <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> + <!--Step11. Go to admin Order page for newly created order--> - <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById"> - <argument name="orderId" value="{$grabOrderNumber}"/> + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="filterOrdersGridById"> + <argument name="entityId" value="$grabOrderId"/> </actionGroup> <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipAction"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml index c873e14797470..9b67208f77492 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -48,7 +48,7 @@ <!--Delete customer--> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <!-- Reset admin order filter --> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clearOrderFilters"/> <!-- Go to the tax rule page and delete the row we created--> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRulesPage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteRule"> From 671ff3a8676ef2e984b66710ec2c44fdcb948879 Mon Sep 17 00:00:00 2001 From: Abhinav Pathak <glo24157@adobe.com> Date: Tue, 12 Oct 2021 21:11:50 +0530 Subject: [PATCH 17/21] AC-1359 intergation fixed for dataset of braintree --- .../Magento/Test/Integrity/Magento/Payment/MethodsTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php index 88c9f14631a53..a308365880d0c 100644 --- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php +++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Magento/Payment/MethodsTest.php @@ -64,6 +64,9 @@ public function testPaymentMethod($code, $methodClass) ->setMode(State::MODE_DEVELOPER); $this->assertNotEmpty($model->getTitle()); foreach ([$model->getFormBlockType(), $model->getInfoBlockType()] as $blockClass) { + if (is_array($blockClass)) { + $blockClass=$blockClass['instance'] ?? ''; + } $message = "Block class: {$blockClass}"; /** @var $block \Magento\Framework\View\Element\Template */ $block = $blockFactory->createBlock($blockClass); From c8777f0717eb4ed0db907fd3763431518df16e2d Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Mon, 18 Oct 2021 22:24:46 +0300 Subject: [PATCH 18/21] Fix static tests Signed-off-by: Denis Kopylov <dkopylov@magenius.team> --- app/code/Magento/Payment/Helper/Data.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index a0089a2b7cde9..fcf3bae7af684 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -47,14 +47,13 @@ class Data extends AbstractHelper /** * Layout + * * @deprecated * @var LayoutInterface */ protected $_layout; /** - * LayoutFactory - * * @var LayoutFactory */ private $layoutFactory; From aaf035d464e309e86845acb6e28c94910ca9ab36 Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Mon, 18 Oct 2021 22:26:54 +0300 Subject: [PATCH 19/21] Move declare stric type after copyright Signed-off-by: Denis Kopylov <dkopylov@magenius.team> --- app/code/Magento/Payment/Helper/Data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index fcf3bae7af684..6909b755bba9f 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -1,9 +1,9 @@ <?php -declare(strict_types=1); /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Payment\Helper; From d8c3e0e38f6d8579510c20ad552b125a158dc188 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Tue, 26 Oct 2021 10:27:27 -0500 Subject: [PATCH 20/21] Update GroupTest.php --- .../Test/Unit/Model/Category/Plugin/Store/GroupTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php index d39ca17979f27..6d85858fbfe3c 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/GroupTest.php @@ -165,10 +165,10 @@ public function testAfterSave() $this->productCollectionMock->expects($this->once()) ->method('addWebsiteFilter') ->willReturn($this->productCollectionMock); - $iterator = new \ArrayIterator([$this->productMock]); + $arrayIteratorMock = new \ArrayIterator([$this->productMock]); $this->productCollectionMock->expects($this->once()) ->method('getIterator') - ->willReturn($iterator); + ->willReturn($arrayIteratorMock); $this->productUrlRewriteGeneratorMock->expects($this->once()) ->method('generate') ->with($this->productMock) @@ -200,7 +200,6 @@ public function testAfterSaveWithNoStoresAssigned() $this->productCollectionMock->expects($this->never())->method('addCategoryIds'); $this->productCollectionMock->expects($this->never()) ->method('addAttributeToSelect'); $this->productCollectionMock->expects($this->never())->method('addWebsiteFilter'); - $iterator = new \ArrayIterator([$this->productMock]); $this->productCollectionMock->expects($this->never())->method('getIterator'); $this->productUrlRewriteGeneratorMock->expects($this->never())->method('generate'); From 2238c665bf72ce0839931dfae15cad8f773e9733 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Tue, 26 Oct 2021 10:35:11 -0500 Subject: [PATCH 21/21] Update ImagesTest.php --- .../testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php index e6a87e57a2c9f..93231abaa5935 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Helper/Wysiwyg/ImagesTest.php @@ -127,6 +127,7 @@ function ($actualResult) { * @param int $storeId * @return Images * @SuppressWarnings(PHPMD.UnusedLocalVariable) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ private function generateHelper($isStaticUrlsAllowed = false, int $storeId = 1) {