From 8529467d79abb67a63db2a0128f6723ec1c06af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 12 Apr 2019 08:13:18 +0200 Subject: [PATCH 001/666] Fix #14958 - remove sales sequence data on store view delete --- .../Magento/SalesSequence/Model/Builder.php | 44 ++++++++++++++++++- .../Model/ResourceModel/Meta.php | 21 +++++++++ .../Model/ResourceModel/Profile.php | 16 +++++++ .../Observer/SequenceRemovalObserver.php | 44 +++++++++++++++++++ app/code/Magento/SalesSequence/etc/events.xml | 12 +++++ 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php create mode 100644 app/code/Magento/SalesSequence/etc/events.xml diff --git a/app/code/Magento/SalesSequence/Model/Builder.php b/app/code/Magento/SalesSequence/Model/Builder.php index 443892b420def..b07e687ec25d9 100644 --- a/app/code/Magento/SalesSequence/Model/Builder.php +++ b/app/code/Magento/SalesSequence/Model/Builder.php @@ -5,10 +5,12 @@ */ namespace Magento\SalesSequence\Model; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\ResourceConnection as AppResource; use Magento\Framework\DB\Ddl\Sequence as DdlSequence; use Magento\Framework\Webapi\Exception; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; +use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; use Psr\Log\LoggerInterface as Logger; /** @@ -83,6 +85,11 @@ class Builder */ protected $logger; + /** + * @var ResourceProfile + */ + private $resourceProfile; + /** * @param ResourceMetadata $resourceMetadata * @param MetaFactory $metaFactory @@ -90,6 +97,7 @@ class Builder * @param AppResource $appResource * @param DdlSequence $ddlSequence * @param Logger $logger + * @param ResourceProfile|null $resourceProfile */ public function __construct( ResourceMetadata $resourceMetadata, @@ -97,7 +105,8 @@ public function __construct( ProfileFactory $profileFactory, AppResource $appResource, DdlSequence $ddlSequence, - Logger $logger + Logger $logger, + ResourceProfile $resourceProfile = null ) { $this->resourceMetadata = $resourceMetadata; $this->metaFactory = $metaFactory; @@ -105,6 +114,7 @@ public function __construct( $this->appResource = $appResource; $this->ddlSequence = $ddlSequence; $this->logger = $logger; + $this->resourceProfile = $resourceProfile ?: ObjectManager::getInstance()->get(ResourceProfile::class); $this->data = array_flip($this->pattern); } @@ -264,4 +274,36 @@ public function create() } $this->data = array_flip($this->pattern); } + + /** + * Deletes all sequence linked entites + * + * @param $storeId + * + * @return void + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function deleteByStoreId($storeId) + { + $metadataIds = $this->resourceMetadata->getIdsByStore($storeId); + $profileIds = $this->resourceProfile->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); + } + } } diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php index 7a4aabea85680..b46844cfab524 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php @@ -92,6 +92,27 @@ public function loadByEntityTypeAndStore($entityType, $storeId) return $meta; } + /** + * Retrieves Metadata Ids by store id + * + * @param int $storeId + * @return int[] + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getIdsByStore($storeId) + { + $connection = $this->getConnection(); + $bind = ['store_id' => $storeId]; + $select = $connection->select()->from( + $this->getMainTable(), + [$this->getIdFieldName()] + )->where( + 'store_id = :store_id' + ); + + return $connection->fetchCol($select, $bind); + } + /** * Using for load sequence profile and setting it into metadata * diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php index 4f1788b0ca353..bb9b5d19c70eb 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php @@ -76,4 +76,20 @@ public function loadActiveProfile($metadataId) } return $profile; } + + /** + * Get profile ids by metadata ids + * @param int[] $metadataIds + * @return int[] + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getProfileIdsByMetadataIds(array $metadataIds) + { + $connection = $this->getConnection(); + $select = $connection->select() + ->from($this->getMainTable(), ['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..4b25bb4c51cee --- /dev/null +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -0,0 +1,44 @@ +sequenceBuilder = $sequenceBuilder; + } + + /** + * @param EventObserver $observer + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function execute(EventObserver $observer) + { + $storeId = $observer->getData('store')->getId(); + $this->sequenceBuilder->deleteByStoreId($storeId); + + return $this; + } +} 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 @@ + + + + + + + From 4c4ae5350087e8e441d1513d45e1e372b15d2ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 12 Apr 2019 08:38:41 +0200 Subject: [PATCH 002/666] Fix #14958 - add unit tests --- .../Unit/Model/ResourceModel/MetaTest.php | 28 +++++++++++++++++++ .../Unit/Model/ResourceModel/ProfileTest.php | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php index 8efa1649a57f0..2b3328fabc4b2 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php @@ -128,6 +128,34 @@ public function testLoadBy() $this->assertEquals($this->meta, $this->resource->loadByEntityTypeAndStore($entityType, $storeId)); } + public function testGetIdsByStore() + { + $metaTableName = 'sequence_meta'; + $metaIdFieldName = 'meta_id'; + $storeId = 1; + $metaIds = [1, 2]; + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->willReturn($metaTableName); + $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); + $this->select->expects($this->at(0)) + ->method('from') + ->with($metaTableName, [$metaIdFieldName]) + ->willReturn($this->select); + $this->select->expects($this->at(1)) + ->method('where') + ->with('store_id = :store_id') + ->willReturn($this->select); + $this->connectionMock->expects($this->once()) + ->method('fetchCol') + ->with($this->select, ['store_id' => $storeId]) + ->willReturn($metaIds); + $this->assertEquals($metaIds, $this->resource->getIdsByStore($storeId)); + } + /** * @param $metaData */ diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php index 28204f01420c9..d1163a9403086 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php @@ -129,4 +129,32 @@ public function testLoadActiveProfile() $this->profile->expects($this->at(1))->method('setData')->with($profileData); $this->assertEquals($this->profile, $this->resource->loadActiveProfile($metaId)); } + + public function testGetProfileIdsByMetadataIds() + { + $profileTableName = 'sequence_profile'; + $profileIdFieldName = 'profile_id'; + $metadataIds = [1, 2]; + $profileIds = [10, 11]; + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->willReturn($profileTableName); + $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); + $this->select->expects($this->at(0)) + ->method('from') + ->with($profileTableName, [$profileIdFieldName]) + ->willReturn($this->select); + $this->select->expects($this->at(1)) + ->method('where') + ->with('meta_id IN (?)', $metadataIds) + ->willReturn($this->select); + $this->connectionMock->expects($this->once()) + ->method('fetchCol') + ->with($this->select) + ->willReturn($profileIds); + $this->assertEquals($profileIds, $this->resource->getProfileIdsByMetadataIds($metadataIds)); + } } From 774d40f3dd91ec3cf0054646054efe546d49e069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 12 Apr 2019 09:03:29 +0200 Subject: [PATCH 003/666] FIx #14958 - add last unit test --- .../Test/Unit/Model/BuilderTest.php | 62 +++++++++++++++++-- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php index 40c5cc32059e7..b29843b63f241 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php @@ -5,6 +5,8 @@ */ namespace Magento\SalesSequence\Test\Unit\Model; +use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; + /** * Class BuilderTest */ @@ -20,6 +22,11 @@ class BuilderTest extends \PHPUnit\Framework\TestCase */ private $resourceSequenceMeta; + /** + * @var ResourceProfile | \PHPUnit_Framework_MockObject_MockObject + */ + private $resourceSequenceProfile; + /** * @var \Magento\SalesSequence\Model\Meta | \PHPUnit_Framework_MockObject_MockObject */ @@ -68,7 +75,11 @@ protected function setUp() ); $this->resourceSequenceMeta = $this->createPartialMock( \Magento\SalesSequence\Model\ResourceModel\Meta::class, - ['loadByEntityTypeAndStore', 'save', 'createSequence'] + ['loadByEntityTypeAndStore', 'save', 'createSequence', 'getIdsByStore', 'load', 'delete'] + ); + $this->resourceSequenceProfile = $this->createPartialMock( + ResourceProfile::class, + ['getProfileIdsByMetadataIds'] ); $this->meta = $this->createPartialMock( \Magento\SalesSequence\Model\Meta::class, @@ -87,9 +98,6 @@ protected function setUp() ['create'] ); $this->profileFactory->expects($this->any())->method('create')->willReturn($this->profile); - $this->resourceMock->expects($this->atLeastOnce()) - ->method('getTableName') - ->willReturn('sequence_lalalka_1'); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->sequenceBuilder = $helper->getObject( @@ -99,7 +107,8 @@ protected function setUp() 'metaFactory' => $this->metaFactory, 'profileFactory' => $this->profileFactory, 'appResource' => $this->resourceMock, - 'ddlSequence' => $this->sequence + 'ddlSequence' => $this->sequence, + 'resourceProfile' => $this->resourceSequenceProfile ] ); } @@ -108,6 +117,9 @@ public function testAddSequenceExistMeta() { $entityType = 'lalalka'; $storeId = 1; + $this->resourceMock->expects($this->atLeastOnce()) + ->method('getTableName') + ->willReturn('sequence_lalalka_1'); $this->resourceSequenceMeta->expects($this->once()) ->method('loadByEntityTypeAndStore') ->with($entityType, $storeId) @@ -138,6 +150,9 @@ public function testAddSequence() $step = 1; $maxValue = 120000; $warningValue = 110000; + $this->resourceMock->expects($this->atLeastOnce()) + ->method('getTableName') + ->willReturn('sequence_lalalka_1'); $this->resourceSequenceMeta->expects($this->once()) ->method('loadByEntityTypeAndStore') ->with($entityType, $storeId) @@ -182,6 +197,43 @@ public function testAddSequence() ->create(); } + public function testDeleteByStoreId() + { + $storeId = 1; + $metadataIds = [1, 2]; + $profileIds = [10, 11]; + $tableName = 'sales_sequence_profile'; + $this->resourceSequenceMeta->expects($this->once()) + ->method('getIdsByStore') + ->with($storeId) + ->willReturn($metadataIds); + $this->resourceSequenceProfile->expects($this->once()) + ->method('getProfileIdsByMetadataIds') + ->with($metadataIds) + ->willReturn($profileIds); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->with($tableName) + ->willReturn($tableName); + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock->expects($this->once()) + ->method('delete') + ->with($tableName, ['profile_id IN (?)' => $profileIds]) + ->willReturn(2); + $this->resourceSequenceMeta->expects($this->any()) + ->method('load') + ->willReturn($this->meta); + $this->connectionMock->expects($this->any()) + ->method('dropTable') + ->willReturn(true); + $this->resourceSequenceMeta->expects($this->any()) + ->method('delete') + ->willReturn($this->resourceSequenceMeta); + $this->sequenceBuilder->deleteByStoreId($storeId); + } + /** * Step create sequence * From 8dab9d767415da4faabc84a25ade4908ff84df45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 12 Apr 2019 21:00:25 +0200 Subject: [PATCH 004/666] FIx #14958 - fix integration tests --- .../TestFramework/Db/Sequence/Builder.php | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php b/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php index 76762afcf0b68..83f066226f373 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php @@ -6,12 +6,13 @@ namespace Magento\TestFramework\Db\Sequence; use Magento\Framework\App\ResourceConnection; -use Magento\Framework\Webapi\Exception; -use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; use Magento\Framework\App\ResourceConnection as AppResource; use Magento\Framework\DB\Ddl\Sequence as DdlSequence; -use Magento\SalesSequence\Model\ProfileFactory; +use Magento\Framework\Webapi\Exception; use Magento\SalesSequence\Model\MetaFactory; +use Magento\SalesSequence\Model\ProfileFactory; +use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; +use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; /** * Class Builder @@ -69,6 +70,11 @@ class Builder extends \Magento\SalesSequence\Model\Builder 'warning_value', ]; + /** + * @var ResourceProfile + */ + protected $resourceProfile; + /** * Concrete data of sequence * @@ -82,19 +88,22 @@ class Builder extends \Magento\SalesSequence\Model\Builder * @param ProfileFactory $profileFactory * @param AppResource $appResource * @param DdlSequence $ddlSequence + * @param ResourceProfile $resourceProfile */ public function __construct( ResourceMetadata $resourceMetadata, MetaFactory $metaFactory, ProfileFactory $profileFactory, AppResource $appResource, - DdlSequence $ddlSequence + DdlSequence $ddlSequence, + ResourceProfile $resourceProfile ) { $this->resourceMetadata = $resourceMetadata; $this->metaFactory = $metaFactory; $this->profileFactory = $profileFactory; $this->appResource = $appResource; $this->ddlSequence = $ddlSequence; + $this->resourceProfile = $resourceProfile; $this->data = array_flip($this->pattern); } @@ -263,4 +272,33 @@ public function create() } $this->data = array_flip($this->pattern); } + + /** + * Deletes all sequence linked entites + * + * @param $storeId + * + * @return void + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function deleteByStoreId($storeId) + { + $metadataIds = $this->resourceMetadata->getIdsByStore($storeId); + $profileIds = $this->resourceProfile->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->resourceMetadata->delete($metadata); + } + } } From 4385c2f5624746a5d88a37edd71b9919ce10ba44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 15 Apr 2019 23:05:35 +0200 Subject: [PATCH 005/666] Revert "FIx #14958 - fix integration tests" This reverts commit 8dab9d767415da4faabc84a25ade4908ff84df45. --- .../TestFramework/Db/Sequence/Builder.php | 46 ++----------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php b/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php index 83f066226f373..76762afcf0b68 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Db/Sequence/Builder.php @@ -6,13 +6,12 @@ namespace Magento\TestFramework\Db\Sequence; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Webapi\Exception; +use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; use Magento\Framework\App\ResourceConnection as AppResource; use Magento\Framework\DB\Ddl\Sequence as DdlSequence; -use Magento\Framework\Webapi\Exception; -use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ProfileFactory; -use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; -use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; +use Magento\SalesSequence\Model\MetaFactory; /** * Class Builder @@ -70,11 +69,6 @@ class Builder extends \Magento\SalesSequence\Model\Builder 'warning_value', ]; - /** - * @var ResourceProfile - */ - protected $resourceProfile; - /** * Concrete data of sequence * @@ -88,22 +82,19 @@ class Builder extends \Magento\SalesSequence\Model\Builder * @param ProfileFactory $profileFactory * @param AppResource $appResource * @param DdlSequence $ddlSequence - * @param ResourceProfile $resourceProfile */ public function __construct( ResourceMetadata $resourceMetadata, MetaFactory $metaFactory, ProfileFactory $profileFactory, AppResource $appResource, - DdlSequence $ddlSequence, - ResourceProfile $resourceProfile + DdlSequence $ddlSequence ) { $this->resourceMetadata = $resourceMetadata; $this->metaFactory = $metaFactory; $this->profileFactory = $profileFactory; $this->appResource = $appResource; $this->ddlSequence = $ddlSequence; - $this->resourceProfile = $resourceProfile; $this->data = array_flip($this->pattern); } @@ -272,33 +263,4 @@ public function create() } $this->data = array_flip($this->pattern); } - - /** - * Deletes all sequence linked entites - * - * @param $storeId - * - * @return void - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function deleteByStoreId($storeId) - { - $metadataIds = $this->resourceMetadata->getIdsByStore($storeId); - $profileIds = $this->resourceProfile->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->resourceMetadata->delete($metadata); - } - } } From 78bfbc86b622c9d92332e46e40f4bc4728c3432e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 15 Apr 2019 23:06:17 +0200 Subject: [PATCH 006/666] Revert "FIx #14958 - add last unit test" This reverts commit 774d40f3dd91ec3cf0054646054efe546d49e069. --- .../Test/Unit/Model/BuilderTest.php | 62 ++----------------- 1 file changed, 5 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php index b29843b63f241..40c5cc32059e7 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/BuilderTest.php @@ -5,8 +5,6 @@ */ namespace Magento\SalesSequence\Test\Unit\Model; -use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; - /** * Class BuilderTest */ @@ -22,11 +20,6 @@ class BuilderTest extends \PHPUnit\Framework\TestCase */ private $resourceSequenceMeta; - /** - * @var ResourceProfile | \PHPUnit_Framework_MockObject_MockObject - */ - private $resourceSequenceProfile; - /** * @var \Magento\SalesSequence\Model\Meta | \PHPUnit_Framework_MockObject_MockObject */ @@ -75,11 +68,7 @@ protected function setUp() ); $this->resourceSequenceMeta = $this->createPartialMock( \Magento\SalesSequence\Model\ResourceModel\Meta::class, - ['loadByEntityTypeAndStore', 'save', 'createSequence', 'getIdsByStore', 'load', 'delete'] - ); - $this->resourceSequenceProfile = $this->createPartialMock( - ResourceProfile::class, - ['getProfileIdsByMetadataIds'] + ['loadByEntityTypeAndStore', 'save', 'createSequence'] ); $this->meta = $this->createPartialMock( \Magento\SalesSequence\Model\Meta::class, @@ -98,6 +87,9 @@ protected function setUp() ['create'] ); $this->profileFactory->expects($this->any())->method('create')->willReturn($this->profile); + $this->resourceMock->expects($this->atLeastOnce()) + ->method('getTableName') + ->willReturn('sequence_lalalka_1'); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->sequenceBuilder = $helper->getObject( @@ -107,8 +99,7 @@ protected function setUp() 'metaFactory' => $this->metaFactory, 'profileFactory' => $this->profileFactory, 'appResource' => $this->resourceMock, - 'ddlSequence' => $this->sequence, - 'resourceProfile' => $this->resourceSequenceProfile + 'ddlSequence' => $this->sequence ] ); } @@ -117,9 +108,6 @@ public function testAddSequenceExistMeta() { $entityType = 'lalalka'; $storeId = 1; - $this->resourceMock->expects($this->atLeastOnce()) - ->method('getTableName') - ->willReturn('sequence_lalalka_1'); $this->resourceSequenceMeta->expects($this->once()) ->method('loadByEntityTypeAndStore') ->with($entityType, $storeId) @@ -150,9 +138,6 @@ public function testAddSequence() $step = 1; $maxValue = 120000; $warningValue = 110000; - $this->resourceMock->expects($this->atLeastOnce()) - ->method('getTableName') - ->willReturn('sequence_lalalka_1'); $this->resourceSequenceMeta->expects($this->once()) ->method('loadByEntityTypeAndStore') ->with($entityType, $storeId) @@ -197,43 +182,6 @@ public function testAddSequence() ->create(); } - public function testDeleteByStoreId() - { - $storeId = 1; - $metadataIds = [1, 2]; - $profileIds = [10, 11]; - $tableName = 'sales_sequence_profile'; - $this->resourceSequenceMeta->expects($this->once()) - ->method('getIdsByStore') - ->with($storeId) - ->willReturn($metadataIds); - $this->resourceSequenceProfile->expects($this->once()) - ->method('getProfileIdsByMetadataIds') - ->with($metadataIds) - ->willReturn($profileIds); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->with($tableName) - ->willReturn($tableName); - $this->resourceMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->connectionMock->expects($this->once()) - ->method('delete') - ->with($tableName, ['profile_id IN (?)' => $profileIds]) - ->willReturn(2); - $this->resourceSequenceMeta->expects($this->any()) - ->method('load') - ->willReturn($this->meta); - $this->connectionMock->expects($this->any()) - ->method('dropTable') - ->willReturn(true); - $this->resourceSequenceMeta->expects($this->any()) - ->method('delete') - ->willReturn($this->resourceSequenceMeta); - $this->sequenceBuilder->deleteByStoreId($storeId); - } - /** * Step create sequence * From 3ff5c067af467c2ee3e36fcaf0cbc478e1022ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 15 Apr 2019 23:14:43 +0200 Subject: [PATCH 007/666] Fix #14958 - move sales sequence removal to external class --- .../Magento/SalesSequence/Model/Builder.php | 44 +---- .../Model/Sequence/DeleteByStore.php | 90 +++++++++++ .../Observer/SequenceRemovalObserver.php | 16 +- .../Unit/Model/Sequence/DeleteByStoreTest.php | 152 ++++++++++++++++++ 4 files changed, 251 insertions(+), 51 deletions(-) create mode 100644 app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php create mode 100644 app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php diff --git a/app/code/Magento/SalesSequence/Model/Builder.php b/app/code/Magento/SalesSequence/Model/Builder.php index b07e687ec25d9..443892b420def 100644 --- a/app/code/Magento/SalesSequence/Model/Builder.php +++ b/app/code/Magento/SalesSequence/Model/Builder.php @@ -5,12 +5,10 @@ */ namespace Magento\SalesSequence\Model; -use Magento\Framework\App\ObjectManager; use Magento\Framework\App\ResourceConnection as AppResource; use Magento\Framework\DB\Ddl\Sequence as DdlSequence; use Magento\Framework\Webapi\Exception; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; -use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; use Psr\Log\LoggerInterface as Logger; /** @@ -85,11 +83,6 @@ class Builder */ protected $logger; - /** - * @var ResourceProfile - */ - private $resourceProfile; - /** * @param ResourceMetadata $resourceMetadata * @param MetaFactory $metaFactory @@ -97,7 +90,6 @@ class Builder * @param AppResource $appResource * @param DdlSequence $ddlSequence * @param Logger $logger - * @param ResourceProfile|null $resourceProfile */ public function __construct( ResourceMetadata $resourceMetadata, @@ -105,8 +97,7 @@ public function __construct( ProfileFactory $profileFactory, AppResource $appResource, DdlSequence $ddlSequence, - Logger $logger, - ResourceProfile $resourceProfile = null + Logger $logger ) { $this->resourceMetadata = $resourceMetadata; $this->metaFactory = $metaFactory; @@ -114,7 +105,6 @@ public function __construct( $this->appResource = $appResource; $this->ddlSequence = $ddlSequence; $this->logger = $logger; - $this->resourceProfile = $resourceProfile ?: ObjectManager::getInstance()->get(ResourceProfile::class); $this->data = array_flip($this->pattern); } @@ -274,36 +264,4 @@ public function create() } $this->data = array_flip($this->pattern); } - - /** - * Deletes all sequence linked entites - * - * @param $storeId - * - * @return void - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function deleteByStoreId($storeId) - { - $metadataIds = $this->resourceMetadata->getIdsByStore($storeId); - $profileIds = $this->resourceProfile->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); - } - } } 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..df2160a35396c --- /dev/null +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -0,0 +1,90 @@ +resourceMetadata = $resourceMetadata; + $this->resourceProfile = $resourceProfile; + $this->metaFactory = $metaFactory; + $this->appResource = $appResource; + } + + /** + * Deletes all sequence linked entites + * + * @param StoreInterface $store + * @return void + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function execute(StoreInterface $store): void + { + $metadataIds = $this->resourceMetadata->getIdsByStore($store->getId()); + $profileIds = $this->resourceProfile->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); + } + } +} diff --git a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php index 4b25bb4c51cee..1e439c1776080 100644 --- a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -4,11 +4,12 @@ * 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\Builder; +use Magento\SalesSequence\Model\Sequence\DeleteByStore; /** * Class SequenceRemovalObserver @@ -16,17 +17,17 @@ class SequenceRemovalObserver implements ObserverInterface { /** - * @var Builder + * @var DeleteByStore */ - private $sequenceBuilder; + private $deleteByStore; /** - * @param Builder $sequenceBuilder + * @param DeleteByStore $deleteByStore */ public function __construct( - Builder $sequenceBuilder + DeleteByStore $deleteByStore ) { - $this->sequenceBuilder = $sequenceBuilder; + $this->deleteByStore = $deleteByStore; } /** @@ -36,8 +37,7 @@ public function __construct( */ public function execute(EventObserver $observer) { - $storeId = $observer->getData('store')->getId(); - $this->sequenceBuilder->deleteByStoreId($storeId); + $this->deleteByStore->execute($observer->getData('store')); 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..711bdbb2bdc92 --- /dev/null +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -0,0 +1,152 @@ +connectionMock = $this->getMockForAbstractClass( + AdapterInterface::class, + [], + '', + false, + false, + true, + ['delete'] + ); + $this->resourceSequenceMeta = $this->createPartialMock( + ResourceMeta::class, + ['getIdsByStore', 'load', 'delete'] + ); + $this->resourceSequenceProfile = $this->createPartialMock( + ResourceProfile::class, + ['getProfileIdsByMetadataIds'] + ); + $this->meta = $this->createPartialMock( + Meta::class, + ['getSequenceTable'] + ); + $this->resourceMock = $this->createMock(ResourceConnection::class); + $this->metaFactory = $this->createPartialMock(MetaFactory::class, ['create']); + $this->metaFactory->expects($this->any())->method('create')->willReturn($this->meta); + $this->store = $this->getMockForAbstractClass( + StoreInterface::class, + [], + '', + false, + false, + true, + ['getId'] + ); + + $helper = new ObjectManager($this); + $this->deleteByStore = $helper->getObject( + DeleteByStore::class, + [ + 'resourceMetadata' => $this->resourceSequenceMeta, + 'resourceProfile' => $this->resourceSequenceProfile, + 'metaFactory' => $this->metaFactory, + 'appResource' => $this->resourceMock, + ] + ); + } + + public function testExecute() + { + $storeId = 1; + $metadataIds = [1, 2]; + $profileIds = [10, 11]; + $tableName = 'sales_sequence_profile'; + $this->store->expects($this->once()) + ->method('getId') + ->willReturn($storeId); + $this->resourceSequenceMeta->expects($this->once()) + ->method('getIdsByStore') + ->with($storeId) + ->willReturn($metadataIds); + $this->resourceSequenceProfile->expects($this->once()) + ->method('getProfileIdsByMetadataIds') + ->with($metadataIds) + ->willReturn($profileIds); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->with($tableName) + ->willReturn($tableName); + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock->expects($this->once()) + ->method('delete') + ->with($tableName, ['profile_id IN (?)' => $profileIds]) + ->willReturn(2); + $this->resourceSequenceMeta->expects($this->any()) + ->method('load') + ->willReturn($this->meta); + $this->connectionMock->expects($this->any()) + ->method('dropTable') + ->willReturn(true); + $this->resourceSequenceMeta->expects($this->any()) + ->method('delete') + ->willReturn($this->resourceSequenceMeta); + $this->deleteByStore->execute($this->store); + } +} From 85b07306e2d3c6764464e382746bc012f5610645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 15 Apr 2019 23:15:57 +0200 Subject: [PATCH 008/666] Fix #14958 - change fields visibility --- .../Magento/SalesSequence/Model/Sequence/DeleteByStore.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php index df2160a35396c..d7c6d4f1559f6 100644 --- a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -22,7 +22,7 @@ class DeleteByStore /** * @var resourceMetadata */ - protected $resourceMetadata; + private $resourceMetadata; /** * @var ResourceProfile @@ -32,12 +32,12 @@ class DeleteByStore /** * @var MetaFactory */ - protected $metaFactory; + private $metaFactory; /** * @var AppResource */ - protected $appResource; + private $appResource; /** * @param ResourceMetadata $resourceMetadata From 309a25ffd61565ab73f688bfff3da72ef877fd25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Tue, 16 Apr 2019 14:53:35 +0200 Subject: [PATCH 009/666] Fix #14958 - declare dependency on Magento_Store --- app/code/Magento/SalesSequence/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json index 3865d9569c529..a0475c14f91a8 100644 --- a/app/code/Magento/SalesSequence/composer.json +++ b/app/code/Magento/SalesSequence/composer.json @@ -6,7 +6,8 @@ }, "require": { "php": "~7.1.3||~7.2.0", - "magento/framework": "*" + "magento/framework": "*", + "magento/module-store": "*" }, "type": "magento2-module", "license": [ From c83a28376898d1bde669bcbae2d3302697b08f95 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 23 Apr 2019 14:11:43 +0300 Subject: [PATCH 010/666] magento/magento2#22296: Static test fix. --- app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php | 1 + app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php | 2 ++ .../Magento/SalesSequence/Observer/SequenceRemovalObserver.php | 2 ++ 3 files changed, 5 insertions(+) diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php index b46844cfab524..dd70a9d2393bb 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php @@ -153,6 +153,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/ResourceModel/Profile.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php index bb9b5d19c70eb..f5e4e8e54eb4b 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\SalesSequence\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\Context as DatabaseContext; @@ -79,6 +80,7 @@ public function loadActiveProfile($metadataId) /** * Get profile ids by metadata ids + * * @param int[] $metadataIds * @return int[] * @throws \Magento\Framework\Exception\LocalizedException diff --git a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php index 1e439c1776080..8bbdb9b12eaeb 100644 --- a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -31,6 +31,8 @@ public function __construct( } /** + * Deletes all sequence linked entities. + * * @param EventObserver $observer * @return $this * @throws \Magento\Framework\Exception\LocalizedException From 328bc51d3838dcd713fe5e4d6b81cade75528708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Wed, 5 Jun 2019 00:15:21 +0200 Subject: [PATCH 011/666] Fix #14958 - apply requested changes --- .../Model/ResourceModel/Meta.php | 21 ---- .../Model/ResourceModel/Meta/Ids.php | 48 +++++++++ .../Model/ResourceModel/Profile.php | 17 ---- .../Model/ResourceModel/Profile/Ids.php | 42 ++++++++ .../Model/Sequence/DeleteByStore.php | 28 ++++-- .../Unit/Model/ResourceModel/Meta/IdsTest.php | 99 +++++++++++++++++++ .../Unit/Model/ResourceModel/MetaTest.php | 28 ------ .../Model/ResourceModel/Profile/IdsTest.php | 99 +++++++++++++++++++ .../Unit/Model/ResourceModel/ProfileTest.php | 28 ------ .../Unit/Model/Sequence/DeleteByStoreTest.php | 35 ++++--- 10 files changed, 329 insertions(+), 116 deletions(-) create mode 100644 app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php create mode 100644 app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php create mode 100644 app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php create mode 100644 app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php index dd70a9d2393bb..8422123c0ca84 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta.php @@ -92,27 +92,6 @@ public function loadByEntityTypeAndStore($entityType, $storeId) return $meta; } - /** - * Retrieves Metadata Ids by store id - * - * @param int $storeId - * @return int[] - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function getIdsByStore($storeId) - { - $connection = $this->getConnection(); - $bind = ['store_id' => $storeId]; - $select = $connection->select()->from( - $this->getMainTable(), - [$this->getIdFieldName()] - )->where( - 'store_id = :store_id' - ); - - return $connection->fetchCol($select, $bind); - } - /** * Using for load sequence profile and setting it into metadata * diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php new file mode 100644 index 0000000000000..05df866128f21 --- /dev/null +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php @@ -0,0 +1,48 @@ +_init('sales_sequence_meta', 'meta_id'); + } + + /** + * Retrieves Metadata Ids by store id + * + * @param int $storeId + * @return int[] + * @throws LocalizedException + */ + public function getByStoreId($storeId) + { + $connection = $this->getConnection(); + $bind = ['store_id' => $storeId]; + $select = $connection->select()->from( + $this->getMainTable(), + [$this->getIdFieldName()] + )->where( + 'store_id = :store_id' + ); + + return $connection->fetchCol($select, $bind); + } +} diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php index f5e4e8e54eb4b..66f351625486b 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php @@ -77,21 +77,4 @@ public function loadActiveProfile($metadataId) } return $profile; } - - /** - * Get profile ids by metadata ids - * - * @param int[] $metadataIds - * @return int[] - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function getProfileIdsByMetadataIds(array $metadataIds) - { - $connection = $this->getConnection(); - $select = $connection->select() - ->from($this->getMainTable(), ['profile_id']) - ->where('meta_id IN (?)', $metadataIds); - - return $connection->fetchCol($select); - } } diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php new file mode 100644 index 0000000000000..219ed6b134668 --- /dev/null +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php @@ -0,0 +1,42 @@ +_init('sales_sequence_profile', 'profile_id'); + } + + /** + * Get profile ids by metadata ids + * + * @param int[] $metadataIds + * @return int[] + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function getByMetadataIds(array $metadataIds) + { + $connection = $this->getConnection(); + $select = $connection->select() + ->from($this->getMainTable(), ['profile_id']) + ->where('meta_id IN (?)', $metadataIds); + + return $connection->fetchCol($select); + } +} diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php index d7c6d4f1559f6..e59bf5f656495 100644 --- a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -10,24 +10,29 @@ use Magento\Framework\App\ResourceConnection as AppResource; use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; -use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; +use Magento\SalesSequence\Model\ResourceModel\Meta\Ids as ResourceMetadataIds; +use Magento\SalesSequence\Model\ResourceModel\Profile\Ids as ResourceProfileIds; use Magento\Store\Api\Data\StoreInterface; /** * Class DeleteByStore - * @api */ class DeleteByStore { /** - * @var resourceMetadata + * @var ResourceMetadata */ private $resourceMetadata; /** - * @var ResourceProfile + * @var ResourceMetadataIds */ - private $resourceProfile; + private $resourceMetadataIds; + + /** + * @var ResourceProfileIds + */ + private $resourceProfileIds; /** * @var MetaFactory @@ -41,18 +46,21 @@ class DeleteByStore /** * @param ResourceMetadata $resourceMetadata - * @param ResourceProfile $resourceProfile + * @param ResourceMetadataIds $resourceMetadataIds + * @param ResourceProfileIds $resourceProfileIds * @param MetaFactory $metaFactory * @param AppResource $appResource */ public function __construct( ResourceMetadata $resourceMetadata, - ResourceProfile $resourceProfile, + ResourceMetadataIds $resourceMetadataIds, + ResourceProfileIds $resourceProfileIds, MetaFactory $metaFactory, AppResource $appResource ) { $this->resourceMetadata = $resourceMetadata; - $this->resourceProfile = $resourceProfile; + $this->resourceMetadataIds = $resourceMetadataIds; + $this->resourceProfileIds = $resourceProfileIds; $this->metaFactory = $metaFactory; $this->appResource = $appResource; } @@ -66,8 +74,8 @@ public function __construct( */ public function execute(StoreInterface $store): void { - $metadataIds = $this->resourceMetadata->getIdsByStore($store->getId()); - $profileIds = $this->resourceProfile->getProfileIdsByMetadataIds($metadataIds); + $metadataIds = $this->resourceMetadataIds->getByStoreId($store->getId()); + $profileIds = $this->resourceProfileIds->getByMetadataIds($metadataIds); $this->appResource->getConnection()->delete( $this->appResource->getTableName('sales_sequence_profile'), diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php new file mode 100644 index 0000000000000..dc8b0f90c1078 --- /dev/null +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php @@ -0,0 +1,99 @@ +connectionMock = $this->getMockForAbstractClass( + AdapterInterface::class, + [], + '', + false, + false, + true, + ['query'] + ); + $this->dbContext = $this->createMock(Context::class); + $this->resourceMock = $this->createPartialMock( + ResourceConnection::class, + ['getConnection', 'getTableName'] + ); + $this->dbContext->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + $this->select = $this->createMock(Select::class); + $this->resource = new Ids( + $this->dbContext + ); + } + + public function testGetByStoreId() + { + $metaTableName = 'sequence_meta'; + $metaIdFieldName = 'meta_id'; + $storeId = 1; + $metaIds = [1, 2]; + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->willReturn($metaTableName); + $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); + $this->select->expects($this->at(0)) + ->method('from') + ->with($metaTableName, [$metaIdFieldName]) + ->willReturn($this->select); + $this->select->expects($this->at(1)) + ->method('where') + ->with('store_id = :store_id') + ->willReturn($this->select); + $this->connectionMock->expects($this->once()) + ->method('fetchCol') + ->with($this->select, ['store_id' => $storeId]) + ->willReturn($metaIds); + $this->assertEquals($metaIds, $this->resource->getByStoreId($storeId)); + } +} diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php index 2b3328fabc4b2..8efa1649a57f0 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php @@ -128,34 +128,6 @@ public function testLoadBy() $this->assertEquals($this->meta, $this->resource->loadByEntityTypeAndStore($entityType, $storeId)); } - public function testGetIdsByStore() - { - $metaTableName = 'sequence_meta'; - $metaIdFieldName = 'meta_id'; - $storeId = 1; - $metaIds = [1, 2]; - $this->resourceMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->willReturn($metaTableName); - $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); - $this->select->expects($this->at(0)) - ->method('from') - ->with($metaTableName, [$metaIdFieldName]) - ->willReturn($this->select); - $this->select->expects($this->at(1)) - ->method('where') - ->with('store_id = :store_id') - ->willReturn($this->select); - $this->connectionMock->expects($this->once()) - ->method('fetchCol') - ->with($this->select, ['store_id' => $storeId]) - ->willReturn($metaIds); - $this->assertEquals($metaIds, $this->resource->getIdsByStore($storeId)); - } - /** * @param $metaData */ diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php new file mode 100644 index 0000000000000..723fd6e8eea06 --- /dev/null +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php @@ -0,0 +1,99 @@ +connectionMock = $this->getMockForAbstractClass( + AdapterInterface::class, + [], + '', + false, + false, + true, + ['query'] + ); + $this->dbContext = $this->createMock(Context::class); + $this->resourceMock = $this->createPartialMock( + ResourceConnection::class, + ['getConnection', 'getTableName'] + ); + $this->dbContext->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + $this->select = $this->createMock(Select::class); + $this->resource = new Ids( + $this->dbContext + ); + } + + public function testGetByMetadataIds() + { + $profileTableName = 'sequence_profile'; + $profileIdFieldName = 'profile_id'; + $metadataIds = [1, 2]; + $profileIds = [10, 11]; + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->resourceMock->expects($this->once()) + ->method('getTableName') + ->willReturn($profileTableName); + $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); + $this->select->expects($this->at(0)) + ->method('from') + ->with($profileTableName, [$profileIdFieldName]) + ->willReturn($this->select); + $this->select->expects($this->at(1)) + ->method('where') + ->with('meta_id IN (?)', $metadataIds) + ->willReturn($this->select); + $this->connectionMock->expects($this->once()) + ->method('fetchCol') + ->with($this->select) + ->willReturn($profileIds); + $this->assertEquals($profileIds, $this->resource->getByMetadataIds($metadataIds)); + } +} diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php index d1163a9403086..28204f01420c9 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php @@ -129,32 +129,4 @@ public function testLoadActiveProfile() $this->profile->expects($this->at(1))->method('setData')->with($profileData); $this->assertEquals($this->profile, $this->resource->loadActiveProfile($metaId)); } - - public function testGetProfileIdsByMetadataIds() - { - $profileTableName = 'sequence_profile'; - $profileIdFieldName = 'profile_id'; - $metadataIds = [1, 2]; - $profileIds = [10, 11]; - $this->resourceMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->willReturn($profileTableName); - $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); - $this->select->expects($this->at(0)) - ->method('from') - ->with($profileTableName, [$profileIdFieldName]) - ->willReturn($this->select); - $this->select->expects($this->at(1)) - ->method('where') - ->with('meta_id IN (?)', $metadataIds) - ->willReturn($this->select); - $this->connectionMock->expects($this->once()) - ->method('fetchCol') - ->with($this->select) - ->willReturn($profileIds); - $this->assertEquals($profileIds, $this->resource->getProfileIdsByMetadataIds($metadataIds)); - } } diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php index 711bdbb2bdc92..d52e6e797c1b8 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -11,7 +11,8 @@ use Magento\SalesSequence\Model\Meta; use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMeta; -use Magento\SalesSequence\Model\ResourceModel\Profile as ResourceProfile; +use Magento\SalesSequence\Model\ResourceModel\Meta\Ids as ResourceMetaIds; +use Magento\SalesSequence\Model\ResourceModel\Profile\Ids as ResourceProfileIds; use Magento\SalesSequence\Model\Sequence\DeleteByStore; use Magento\Store\Api\Data\StoreInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -33,9 +34,14 @@ class DeleteByStoreTest extends TestCase private $resourceSequenceMeta; /** - * @var ResourceProfile | MockObject + * @var ResourceMetaIds | MockObject */ - private $resourceSequenceProfile; + private $resourceSequenceMetaIds; + + /** + * @var ResourceProfileIds | MockObject + */ + private $resourceSequenceProfileIds; /** * @var Meta | MockObject @@ -75,11 +81,15 @@ protected function setUp() ); $this->resourceSequenceMeta = $this->createPartialMock( ResourceMeta::class, - ['getIdsByStore', 'load', 'delete'] + ['load', 'delete'] + ); + $this->resourceSequenceMetaIds = $this->createPartialMock( + ResourceMetaIds::class, + ['getByStoreId'] ); - $this->resourceSequenceProfile = $this->createPartialMock( - ResourceProfile::class, - ['getProfileIdsByMetadataIds'] + $this->resourceSequenceProfileIds = $this->createPartialMock( + ResourceProfileIds::class, + ['getByMetadataIds'] ); $this->meta = $this->createPartialMock( Meta::class, @@ -102,8 +112,9 @@ protected function setUp() $this->deleteByStore = $helper->getObject( DeleteByStore::class, [ + 'resourceMetadataIds' => $this->resourceSequenceMetaIds, 'resourceMetadata' => $this->resourceSequenceMeta, - 'resourceProfile' => $this->resourceSequenceProfile, + 'resourceProfileIds' => $this->resourceSequenceProfileIds, 'metaFactory' => $this->metaFactory, 'appResource' => $this->resourceMock, ] @@ -119,12 +130,12 @@ public function testExecute() $this->store->expects($this->once()) ->method('getId') ->willReturn($storeId); - $this->resourceSequenceMeta->expects($this->once()) - ->method('getIdsByStore') + $this->resourceSequenceMetaIds->expects($this->once()) + ->method('getByStoreId') ->with($storeId) ->willReturn($metadataIds); - $this->resourceSequenceProfile->expects($this->once()) - ->method('getProfileIdsByMetadataIds') + $this->resourceSequenceProfileIds->expects($this->once()) + ->method('getByMetadataIds') ->with($metadataIds) ->willReturn($profileIds); $this->resourceMock->expects($this->once()) From 7c078cf8158580bf704c6fb79e0bcd8e26ffe5d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Wed, 5 Jun 2019 00:17:14 +0200 Subject: [PATCH 012/666] Fix #14958 - add declare strict_types --- app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php | 1 - .../Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php index 66f351625486b..4f1788b0ca353 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile.php @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\SalesSequence\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\Context as DatabaseContext; diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php index 219ed6b134668..49015e29cbff2 100644 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php +++ b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\SalesSequence\Model\ResourceModel\Profile; From 76b2085cc7b82dc957728183d5dec800ec18be4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 7 Jun 2019 18:43:15 +0200 Subject: [PATCH 013/666] Fix #14958 - move two methods from resource models to private methods of DeleteByStore --- .../Model/ResourceModel/Meta/Ids.php | 48 --------- .../Model/ResourceModel/Profile/Ids.php | 43 -------- .../Model/Sequence/DeleteByStore.php | 62 ++++++++---- .../Unit/Model/ResourceModel/Meta/IdsTest.php | 99 ------------------- .../Model/ResourceModel/Profile/IdsTest.php | 99 ------------------- .../Unit/Model/Sequence/DeleteByStoreTest.php | 75 +++++++------- 6 files changed, 77 insertions(+), 349 deletions(-) delete mode 100644 app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php delete mode 100644 app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php delete mode 100644 app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php delete mode 100644 app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php deleted file mode 100644 index 05df866128f21..0000000000000 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Meta/Ids.php +++ /dev/null @@ -1,48 +0,0 @@ -_init('sales_sequence_meta', 'meta_id'); - } - - /** - * Retrieves Metadata Ids by store id - * - * @param int $storeId - * @return int[] - * @throws LocalizedException - */ - public function getByStoreId($storeId) - { - $connection = $this->getConnection(); - $bind = ['store_id' => $storeId]; - $select = $connection->select()->from( - $this->getMainTable(), - [$this->getIdFieldName()] - )->where( - 'store_id = :store_id' - ); - - return $connection->fetchCol($select, $bind); - } -} diff --git a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php b/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php deleted file mode 100644 index 49015e29cbff2..0000000000000 --- a/app/code/Magento/SalesSequence/Model/ResourceModel/Profile/Ids.php +++ /dev/null @@ -1,43 +0,0 @@ -_init('sales_sequence_profile', 'profile_id'); - } - - /** - * Get profile ids by metadata ids - * - * @param int[] $metadataIds - * @return int[] - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function getByMetadataIds(array $metadataIds) - { - $connection = $this->getConnection(); - $select = $connection->select() - ->from($this->getMainTable(), ['profile_id']) - ->where('meta_id IN (?)', $metadataIds); - - return $connection->fetchCol($select); - } -} diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php index e59bf5f656495..77b30d385eae9 100644 --- a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -10,8 +10,6 @@ use Magento\Framework\App\ResourceConnection as AppResource; use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; -use Magento\SalesSequence\Model\ResourceModel\Meta\Ids as ResourceMetadataIds; -use Magento\SalesSequence\Model\ResourceModel\Profile\Ids as ResourceProfileIds; use Magento\Store\Api\Data\StoreInterface; /** @@ -24,16 +22,6 @@ class DeleteByStore */ private $resourceMetadata; - /** - * @var ResourceMetadataIds - */ - private $resourceMetadataIds; - - /** - * @var ResourceProfileIds - */ - private $resourceProfileIds; - /** * @var MetaFactory */ @@ -46,21 +34,15 @@ class DeleteByStore /** * @param ResourceMetadata $resourceMetadata - * @param ResourceMetadataIds $resourceMetadataIds - * @param ResourceProfileIds $resourceProfileIds * @param MetaFactory $metaFactory * @param AppResource $appResource */ public function __construct( ResourceMetadata $resourceMetadata, - ResourceMetadataIds $resourceMetadataIds, - ResourceProfileIds $resourceProfileIds, MetaFactory $metaFactory, AppResource $appResource ) { $this->resourceMetadata = $resourceMetadata; - $this->resourceMetadataIds = $resourceMetadataIds; - $this->resourceProfileIds = $resourceProfileIds; $this->metaFactory = $metaFactory; $this->appResource = $appResource; } @@ -70,12 +52,12 @@ public function __construct( * * @param StoreInterface $store * @return void - * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Exception */ public function execute(StoreInterface $store): void { - $metadataIds = $this->resourceMetadataIds->getByStoreId($store->getId()); - $profileIds = $this->resourceProfileIds->getByMetadataIds($metadataIds); + $metadataIds = $this->getMetadataIdsByStoreId($store->getId()); + $profileIds = $this->getProfileIdsByMetadataIds($metadataIds); $this->appResource->getConnection()->delete( $this->appResource->getTableName('sales_sequence_profile'), @@ -95,4 +77,42 @@ public function execute(StoreInterface $store): void $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/Test/Unit/Model/ResourceModel/Meta/IdsTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php deleted file mode 100644 index dc8b0f90c1078..0000000000000 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Meta/IdsTest.php +++ /dev/null @@ -1,99 +0,0 @@ -connectionMock = $this->getMockForAbstractClass( - AdapterInterface::class, - [], - '', - false, - false, - true, - ['query'] - ); - $this->dbContext = $this->createMock(Context::class); - $this->resourceMock = $this->createPartialMock( - ResourceConnection::class, - ['getConnection', 'getTableName'] - ); - $this->dbContext->expects($this->once())->method('getResources')->willReturn($this->resourceMock); - $this->select = $this->createMock(Select::class); - $this->resource = new Ids( - $this->dbContext - ); - } - - public function testGetByStoreId() - { - $metaTableName = 'sequence_meta'; - $metaIdFieldName = 'meta_id'; - $storeId = 1; - $metaIds = [1, 2]; - $this->resourceMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->willReturn($metaTableName); - $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); - $this->select->expects($this->at(0)) - ->method('from') - ->with($metaTableName, [$metaIdFieldName]) - ->willReturn($this->select); - $this->select->expects($this->at(1)) - ->method('where') - ->with('store_id = :store_id') - ->willReturn($this->select); - $this->connectionMock->expects($this->once()) - ->method('fetchCol') - ->with($this->select, ['store_id' => $storeId]) - ->willReturn($metaIds); - $this->assertEquals($metaIds, $this->resource->getByStoreId($storeId)); - } -} diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php deleted file mode 100644 index 723fd6e8eea06..0000000000000 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/Profile/IdsTest.php +++ /dev/null @@ -1,99 +0,0 @@ -connectionMock = $this->getMockForAbstractClass( - AdapterInterface::class, - [], - '', - false, - false, - true, - ['query'] - ); - $this->dbContext = $this->createMock(Context::class); - $this->resourceMock = $this->createPartialMock( - ResourceConnection::class, - ['getConnection', 'getTableName'] - ); - $this->dbContext->expects($this->once())->method('getResources')->willReturn($this->resourceMock); - $this->select = $this->createMock(Select::class); - $this->resource = new Ids( - $this->dbContext - ); - } - - public function testGetByMetadataIds() - { - $profileTableName = 'sequence_profile'; - $profileIdFieldName = 'profile_id'; - $metadataIds = [1, 2]; - $profileIds = [10, 11]; - $this->resourceMock->expects($this->any()) - ->method('getConnection') - ->willReturn($this->connectionMock); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->willReturn($profileTableName); - $this->connectionMock->expects($this->any())->method('select')->willReturn($this->select); - $this->select->expects($this->at(0)) - ->method('from') - ->with($profileTableName, [$profileIdFieldName]) - ->willReturn($this->select); - $this->select->expects($this->at(1)) - ->method('where') - ->with('meta_id IN (?)', $metadataIds) - ->willReturn($this->select); - $this->connectionMock->expects($this->once()) - ->method('fetchCol') - ->with($this->select) - ->willReturn($profileIds); - $this->assertEquals($profileIds, $this->resource->getByMetadataIds($metadataIds)); - } -} diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php index d52e6e797c1b8..6c2128b113ae8 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -7,12 +7,11 @@ 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\ResourceModel\Meta\Ids as ResourceMetaIds; -use Magento\SalesSequence\Model\ResourceModel\Profile\Ids as ResourceProfileIds; use Magento\SalesSequence\Model\Sequence\DeleteByStore; use Magento\Store\Api\Data\StoreInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -33,16 +32,6 @@ class DeleteByStoreTest extends TestCase */ private $resourceSequenceMeta; - /** - * @var ResourceMetaIds | MockObject - */ - private $resourceSequenceMetaIds; - - /** - * @var ResourceProfileIds | MockObject - */ - private $resourceSequenceProfileIds; - /** * @var Meta | MockObject */ @@ -63,6 +52,11 @@ class DeleteByStoreTest extends TestCase */ private $resourceMock; + /** + * @var Select | MockObject + */ + private $select; + /** * @var StoreInterface | MockObject */ @@ -77,25 +71,18 @@ protected function setUp() false, false, true, - ['delete'] + ['delete', 'query'] ); $this->resourceSequenceMeta = $this->createPartialMock( ResourceMeta::class, ['load', 'delete'] ); - $this->resourceSequenceMetaIds = $this->createPartialMock( - ResourceMetaIds::class, - ['getByStoreId'] - ); - $this->resourceSequenceProfileIds = $this->createPartialMock( - ResourceProfileIds::class, - ['getByMetadataIds'] - ); $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->expects($this->any())->method('create')->willReturn($this->meta); $this->store = $this->getMockForAbstractClass( @@ -112,9 +99,7 @@ protected function setUp() $this->deleteByStore = $helper->getObject( DeleteByStore::class, [ - 'resourceMetadataIds' => $this->resourceSequenceMetaIds, 'resourceMetadata' => $this->resourceSequenceMeta, - 'resourceProfileIds' => $this->resourceSequenceProfileIds, 'metaFactory' => $this->metaFactory, 'appResource' => $this->resourceMock, ] @@ -123,31 +108,43 @@ protected function setUp() public function testExecute() { + $profileTableName = 'sales_sequence_profile'; $storeId = 1; $metadataIds = [1, 2]; $profileIds = [10, 11]; - $tableName = 'sales_sequence_profile'; $this->store->expects($this->once()) ->method('getId') ->willReturn($storeId); - $this->resourceSequenceMetaIds->expects($this->once()) - ->method('getByStoreId') - ->with($storeId) - ->willReturn($metadataIds); - $this->resourceSequenceProfileIds->expects($this->once()) - ->method('getByMetadataIds') - ->with($metadataIds) - ->willReturn($profileIds); - $this->resourceMock->expects($this->once()) - ->method('getTableName') - ->with($tableName) - ->willReturn($tableName); - $this->resourceMock->expects($this->any()) - ->method('getConnection') + $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( + /** @SuppressWarnings(PHPMD.UnusedFormalParameter) */ + 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($tableName, ['profile_id IN (?)' => $profileIds]) + ->with($profileTableName, ['profile_id IN (?)' => $profileIds]) ->willReturn(2); $this->resourceSequenceMeta->expects($this->any()) ->method('load') From 11f013c30d876f3c182b4d901e0530d79e01bcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Tue, 13 Aug 2019 21:13:36 +0200 Subject: [PATCH 014/666] Fix #14958 - remove requirement of magento/module-store --- .../Model/Sequence/DeleteByStore.php | 7 +++---- .../Observer/SequenceRemovalObserver.php | 4 +++- .../Unit/Model/Sequence/DeleteByStoreTest.php | 20 +------------------ app/code/Magento/SalesSequence/composer.json | 3 +-- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php index 77b30d385eae9..7e6ef8b2f3dda 100644 --- a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -10,7 +10,6 @@ use Magento\Framework\App\ResourceConnection as AppResource; use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; -use Magento\Store\Api\Data\StoreInterface; /** * Class DeleteByStore @@ -50,13 +49,13 @@ public function __construct( /** * Deletes all sequence linked entites * - * @param StoreInterface $store + * @param int $storeId * @return void * @throws \Exception */ - public function execute(StoreInterface $store): void + public function execute($storeId): void { - $metadataIds = $this->getMetadataIdsByStoreId($store->getId()); + $metadataIds = $this->getMetadataIdsByStoreId($storeId); $profileIds = $this->getProfileIdsByMetadataIds($metadataIds); $this->appResource->getConnection()->delete( diff --git a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php index 8bbdb9b12eaeb..4ed4752b27150 100644 --- a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -39,7 +39,9 @@ public function __construct( */ public function execute(EventObserver $observer) { - $this->deleteByStore->execute($observer->getData('store')); + 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 index 6c2128b113ae8..a3877d551fe11 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -13,7 +13,6 @@ use Magento\SalesSequence\Model\MetaFactory; use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMeta; use Magento\SalesSequence\Model\Sequence\DeleteByStore; -use Magento\Store\Api\Data\StoreInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -57,11 +56,6 @@ class DeleteByStoreTest extends TestCase */ private $select; - /** - * @var StoreInterface | MockObject - */ - private $store; - protected function setUp() { $this->connectionMock = $this->getMockForAbstractClass( @@ -85,15 +79,6 @@ protected function setUp() $this->select = $this->createMock(Select::class); $this->metaFactory = $this->createPartialMock(MetaFactory::class, ['create']); $this->metaFactory->expects($this->any())->method('create')->willReturn($this->meta); - $this->store = $this->getMockForAbstractClass( - StoreInterface::class, - [], - '', - false, - false, - true, - ['getId'] - ); $helper = new ObjectManager($this); $this->deleteByStore = $helper->getObject( @@ -112,9 +97,6 @@ public function testExecute() $storeId = 1; $metadataIds = [1, 2]; $profileIds = [10, 11]; - $this->store->expects($this->once()) - ->method('getId') - ->willReturn($storeId); $this->resourceMock->method('getTableName') ->willReturnCallback(static function ($tableName) { return $tableName; @@ -155,6 +137,6 @@ static function ($arg, $arg2) use ($metadataIds, $profileIds) { $this->resourceSequenceMeta->expects($this->any()) ->method('delete') ->willReturn($this->resourceSequenceMeta); - $this->deleteByStore->execute($this->store); + $this->deleteByStore->execute($storeId); } } diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json index a0475c14f91a8..3865d9569c529 100644 --- a/app/code/Magento/SalesSequence/composer.json +++ b/app/code/Magento/SalesSequence/composer.json @@ -6,8 +6,7 @@ }, "require": { "php": "~7.1.3||~7.2.0", - "magento/framework": "*", - "magento/module-store": "*" + "magento/framework": "*" }, "type": "magento2-module", "license": [ From 68d1bed1d13ef3c68bc3da0bb578389db56e795c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Wed, 14 Aug 2019 07:30:05 +0200 Subject: [PATCH 015/666] fix #14958 - fix static check --- .../Unit/Model/Sequence/DeleteByStoreTest.php | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php index a3877d551fe11..1b652ac99b866 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -78,7 +78,7 @@ protected function setUp() $this->resourceMock = $this->createMock(ResourceConnection::class); $this->select = $this->createMock(Select::class); $this->metaFactory = $this->createPartialMock(MetaFactory::class, ['create']); - $this->metaFactory->expects($this->any())->method('create')->willReturn($this->meta); + $this->metaFactory->method('create')->willReturn($this->meta); $helper = new ObjectManager($this); $this->deleteByStore = $helper->getObject( @@ -91,6 +91,10 @@ protected function setUp() ); } + /** + * @throws \Exception + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ public function testExecute() { $profileTableName = 'sales_sequence_profile'; @@ -98,9 +102,11 @@ public function testExecute() $metadataIds = [1, 2]; $profileIds = [10, 11]; $this->resourceMock->method('getTableName') - ->willReturnCallback(static function ($tableName) { - return $tableName; - }); + ->willReturnCallback( + static function ($tableName) { + return $tableName; + } + ); $this->resourceMock->method('getConnection') ->willReturn($this->connectionMock); $this->connectionMock @@ -114,7 +120,6 @@ public function testExecute() $this->connectionMock->method('fetchCol') ->willReturnCallback( - /** @SuppressWarnings(PHPMD.UnusedFormalParameter) */ static function ($arg, $arg2) use ($metadataIds, $profileIds) { if (array_key_exists('store', $arg2)) { return $metadataIds; @@ -128,13 +133,13 @@ static function ($arg, $arg2) use ($metadataIds, $profileIds) { ->method('delete') ->with($profileTableName, ['profile_id IN (?)' => $profileIds]) ->willReturn(2); - $this->resourceSequenceMeta->expects($this->any()) + $this->resourceSequenceMeta ->method('load') ->willReturn($this->meta); - $this->connectionMock->expects($this->any()) + $this->connectionMock ->method('dropTable') ->willReturn(true); - $this->resourceSequenceMeta->expects($this->any()) + $this->resourceSequenceMeta ->method('delete') ->willReturn($this->resourceSequenceMeta); $this->deleteByStore->execute($storeId); From e89a604e1010c98e37956719db96416fec515a96 Mon Sep 17 00:00:00 2001 From: Andreas von Studnitz Date: Fri, 6 Sep 2019 11:50:58 +0200 Subject: [PATCH 016/666] Fix return type --- .../Magento/Framework/Pricing/PriceCurrencyInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php index eb379b54d257f..72068586e3027 100644 --- a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php +++ b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php @@ -47,7 +47,7 @@ public function convertAndRound($amount, $scope = null, $currency = null, $preci * @param int $precision * @param null|string|bool|int|\Magento\Framework\App\ScopeInterface $scope * @param \Magento\Framework\Model\AbstractModel|string|null $currency - * @return float + * @return string */ public function format( $amount, From 098770d4dca34b3a5c10d3ed5f7bc27c12d3f20d Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <51681487+engcom-Foxtrot@users.noreply.github.com> Date: Mon, 9 Sep 2019 14:41:50 +0300 Subject: [PATCH 017/666] magento/magento2#24485: Static test fix. --- .../Magento/Framework/Pricing/PriceCurrencyInterface.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php index 72068586e3027..ab3d26f3e0c6c 100644 --- a/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php +++ b/lib/internal/Magento/Framework/Pricing/PriceCurrencyInterface.php @@ -13,9 +13,6 @@ */ interface PriceCurrencyInterface { - /** - * Default precision - */ const DEFAULT_PRECISION = 2; /** From cd3b244cf3140821ee34bb52fc1cf8259988386d Mon Sep 17 00:00:00 2001 From: Vinai Kopp Date: Mon, 2 Sep 2019 12:21:00 +0200 Subject: [PATCH 018/666] Allow construction of products with custom_attributes This patch does two things: 1. Currently it is not possible to pass an array with `custom_attributes` to the `\Magento\Catalog\Model\Product` constructor (it causes a fatal error). The reason is because the `filterCustomAttribute` and `eavConfig` arguments are assigned after the call to `parent::__construct`. However, the properties are used during the `parent::__construct` calls. The flow of execution is as follows: Product::__construct -> Catalog\Model\AbstractModel::__construct Catalog\Model\AbstractModel::__construct -> AbstractExtensibleModel::__construct AbstractExtensibleModel::__construct -> AbstractExtensibleModel::filterCustomAttributes AbstractExtensibleModel::filterCustomAttributes -> AbstractExtensibleModel::getCustomAttributesCodes ...which is overridden by Product::getCustomAttributesCodes getCustomAttributesCodes expectes the `filterCustomAttribute` and `eavConfig` properties to be set if `custom_attributes` are present in `$data`, but they are still null because the `Product::__construct` method has not yet completed. The fix this PR applies is to assign the properties before the call to `parent::__construct`. The bug and fix are covered by the integration test: `\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesMapInData` 2. The method `AbstractExtensibleModel::filterCustomAttribute` expects the `custom_attributes` in `$data` to be a simple map from codes to values, e.g. `['category_ids => '1,2']`. However, the method `\Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray` generates a numerically indexed custom attributes array, where each custom attribute is a sub-array with a `attribute_code` and `value` record. This PR allows passing such an `custom_attributes` array into the `Product` model constructor. Currently it would be ignored, but with this patch the code checks if `custom_attributes` is numerically indexed, and if so, flattens the sub-arrays into the expected map format. To illustrate the difference of the `custom_attributes` array formats: Map: [ 'custom_attributes' => [ 'category_ids' => '1,2', 'tax_class_id' => '3', ] ] Numerically indexed array of sub-arrays: [ 'custom_attributes' => [ [ 'attribute_code' => 'category_ids', 'value' => '1,2' ], [ 'attribute_code' => 'tax_class_id', 'value' => '3' ], ] ] This improvement is covered by the integration test `\Magento\Catalog\Model\ProductTest::testConstructionWithCustomAttributesArrayInData` --- app/code/Magento/Catalog/Model/Product.php | 19 +++---- .../Magento/Catalog/Model/ProductTest.php | 54 ++++++++++++++++--- .../Model/AbstractExtensibleModel.php | 29 +++++++++- 3 files changed, 83 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 1b7552c82276d..2f3c219d66cbb 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -472,6 +472,9 @@ public function __construct( $this->mediaGalleryEntryConverterPool = $mediaGalleryEntryConverterPool; $this->dataObjectHelper = $dataObjectHelper; $this->joinProcessor = $joinProcessor; + $this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class); + $this->filterCustomAttribute = $filterCustomAttribute + ?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class); parent::__construct( $context, $registry, @@ -482,9 +485,6 @@ public function __construct( $resourceCollection, $data ); - $this->eavConfig = $config ?? ObjectManager::getInstance()->get(\Magento\Eav\Model\Config::class); - $this->filterCustomAttribute = $filterCustomAttribute - ?? ObjectManager::getInstance()->get(FilterProductCustomAttribute::class); } /** @@ -835,12 +835,13 @@ public function getStoreIds() if (!$this->isObjectNew() && $this->_storeManager->isSingleStoreMode()) { $websiteIds = array_keys($websiteIds); } - foreach ($websiteIds as $websiteId) { - $websiteStores = $this->_storeManager->getWebsite($websiteId)->getStoreIds(); - foreach ($websiteStores as $websiteStore) { - $storeIds []= $websiteStore; - } - } + $websiteStoreIds = array_map( + function ($websiteId): array { + return $this->_storeManager->getWebsite($websiteId)->getStoreIds(); + }, + $websiteIds + ); + $storeIds = array_merge($storeIds, ...$websiteStoreIds); } $this->setStoreIds($storeIds); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index c34120404a950..0754ec0c06633 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -8,7 +8,9 @@ namespace Magento\Catalog\Model; +use Magento\Eav\Model\Config as EavConfig; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\TestFramework\ObjectManager; /** * Tests product model: @@ -49,8 +51,8 @@ protected function setUp() } /** - * @throws \Magento\Framework\Exception\FileSystemException * @return void + * @throws \Magento\Framework\Exception\FileSystemException */ public static function tearDownAfterClass() { @@ -307,9 +309,9 @@ public function testIsSalable() $this->_model = $this->productRepository->get('simple'); // fixture - $this->assertTrue((bool)$this->_model->isSalable()); - $this->assertTrue((bool)$this->_model->isSaleable()); - $this->assertTrue((bool)$this->_model->isAvailable()); + $this->assertTrue((bool) $this->_model->isSalable()); + $this->assertTrue((bool) $this->_model->isSaleable()); + $this->assertTrue((bool) $this->_model->isAvailable()); $this->assertTrue($this->_model->isInStock()); } @@ -324,9 +326,9 @@ public function testIsNotSalableWhenStatusDisabled() $this->_model = $this->productRepository->get('simple'); $this->_model->setStatus(0); - $this->assertFalse((bool)$this->_model->isSalable()); - $this->assertFalse((bool)$this->_model->isSaleable()); - $this->assertFalse((bool)$this->_model->isAvailable()); + $this->assertFalse((bool) $this->_model->isSalable()); + $this->assertFalse((bool) $this->_model->isSaleable()); + $this->assertFalse((bool) $this->_model->isAvailable()); $this->assertFalse($this->_model->isInStock()); } @@ -585,7 +587,7 @@ public function testGetOptions() continue; } foreach ($option->getValues() as $value) { - $this->assertEquals($expectedValue[$value->getSku()], (float)$value->getPrice()); + $this->assertEquals($expectedValue[$value->getSku()], (float) $value->getPrice()); } } } @@ -632,4 +634,40 @@ public function productWithBackordersDataProvider(): array [1, 1, true], ]; } + + public function testConstructionWithCustomAttributesMapInData() + { + $data = [ + 'custom_attributes' => [ + 'tax_class_id' => '3', + 'category_ids' => '1,2' + ], + ]; + + /** @var Product $product */ + $product = ObjectManager::getInstance()->create(Product::class, ['data' => $data]); + $this->assertSame($product->getCustomAttribute('tax_class_id')->getValue(), '3'); + $this->assertSame($product->getCustomAttribute('category_ids')->getValue(), '1,2'); + } + + public function testConstructionWithCustomAttributesArrayInData() + { + $data = [ + 'custom_attributes' => [ + [ + 'attribute_code' => 'tax_class_id', + 'value' => '3' + ], + [ + 'attribute_code' => 'category_ids', + 'value' => '1,2' + ] + ], + ]; + + /** @var Product $product */ + $product = ObjectManager::getInstance()->create(Product::class, ['data' => $data]); + $this->assertSame($product->getCustomAttribute('tax_class_id')->getValue(), '3'); + $this->assertSame($product->getCustomAttribute('category_ids')->getValue(), '1,2'); + } } diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 949e002a14208..b88954bd21ce8 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -74,6 +74,28 @@ public function __construct( } } + /** + * Convert the custom attributes array format to map format + * + * The method \Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray generates a custom_attributes + * array representation where each custom attribute is a sub-array with a `attribute_code and value key. + * This method maps such an array to the plain code => value map format exprected by filterCustomAttributes + * + * @param array[] $customAttributesData + * @return array + */ + private function flattenCustomAttributesArrayToMap(array $customAttributesData): array + { + return array_reduce( + $customAttributesData, + function (array $acc, array $customAttribute): array { + $acc[$customAttribute['attribute_code']] = $customAttribute['value']; + return $acc; + }, + [] + ); + } + /** * Verify custom attributes set on $data and unset if not a valid custom attribute * @@ -85,9 +107,12 @@ protected function filterCustomAttributes($data) if (empty($data[self::CUSTOM_ATTRIBUTES])) { return $data; } - $customAttributesCodes = $this->getCustomAttributesCodes(); + if (isset($data[self::CUSTOM_ATTRIBUTES][0])) { + $data[self::CUSTOM_ATTRIBUTES] = $this->flattenCustomAttributesArrayToMap($data[self::CUSTOM_ATTRIBUTES]); + } + $customAttributesCodes = $this->getCustomAttributesCodes(); $data[self::CUSTOM_ATTRIBUTES] = array_intersect_key( - (array)$data[self::CUSTOM_ATTRIBUTES], + (array) $data[self::CUSTOM_ATTRIBUTES], array_flip($customAttributesCodes) ); foreach ($data[self::CUSTOM_ATTRIBUTES] as $code => $value) { From a15f33557d72d4ab05a99e9583fbfc0e2daa2ba2 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Sun, 15 Sep 2019 16:12:58 -0400 Subject: [PATCH 019/666] Fix for the issue #24547 --- .../Customer/Model/Account/Redirect.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) mode change 100644 => 100755 app/code/Magento/Customer/Model/Account/Redirect.php diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php old mode 100644 new mode 100755 index 2ccaaea45680c..b9a669b8ba990 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -9,6 +9,7 @@ use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\App\RequestInterface; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; use Magento\Framework\Url\HostChecker; use Magento\Framework\UrlInterface; use Magento\Store\Model\ScopeInterface; @@ -69,6 +70,11 @@ class Redirect */ protected $cookieManager; + /** + * @var CookieMetadataFactory + */ + protected $cookieMetadataFactory; + /** * @var HostChecker */ @@ -88,6 +94,7 @@ class Redirect * @param DecoderInterface $urlDecoder * @param CustomerUrl $customerUrl * @param ResultFactory $resultFactory + * @param CookieMetadataFactory $cookieMetadataFactory * @param HostChecker|null $hostChecker */ public function __construct( @@ -99,6 +106,7 @@ public function __construct( DecoderInterface $urlDecoder, CustomerUrl $customerUrl, ResultFactory $resultFactory, + CookieMetadataFactory $cookieMetadataFactory, HostChecker $hostChecker = null ) { $this->request = $request; @@ -109,6 +117,7 @@ public function __construct( $this->urlDecoder = $urlDecoder; $this->customerUrl = $customerUrl; $this->resultFactory = $resultFactory; + $this->cookieMetadataFactory = $cookieMetadataFactory; $this->hostChecker = $hostChecker ?: ObjectManager::getInstance()->get(HostChecker::class); } @@ -279,7 +288,11 @@ public function getRedirectCookie() */ public function setRedirectCookie($route) { - $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route); + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setHttpOnly(true) + ->setDuration(3600) + ->setPath($this->storeManager->getStore()->getStorePath()); + $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route, $cookieMetadata); } /** @@ -289,6 +302,8 @@ public function setRedirectCookie($route) */ public function clearRedirectCookie() { - $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL); + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setPath($this->storeManager->getStore()->getStorePath()); + $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL, $cookieMetadata); } } From 664056fc0e4fedc5c10aac2d14537b285dbefffd Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Wed, 18 Sep 2019 11:17:21 -0400 Subject: [PATCH 020/666] Fix for the issue #24547 Magento\Customer\Model\Account\Redirect::setRedirectCookie() not properly working --- .../Api/RedirectCookieManagerInterface.php | 41 +++++++++++ .../Customer/Model/Account/Redirect.php | 27 ++++--- .../Customer/Model/RedirectCookieManager.php | 72 +++++++++++++++++++ .../Test/Unit/Model/Account/RedirectTest.php | 11 +++ app/code/Magento/Customer/etc/di.xml | 3 + 5 files changed, 139 insertions(+), 15 deletions(-) create mode 100755 app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php create mode 100755 app/code/Magento/Customer/Model/RedirectCookieManager.php mode change 100644 => 100755 app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php mode change 100644 => 100755 app/code/Magento/Customer/etc/di.xml diff --git a/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php b/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php new file mode 100755 index 0000000000000..5f4f1f6f917de --- /dev/null +++ b/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php @@ -0,0 +1,41 @@ +request = $request; @@ -117,7 +120,7 @@ public function __construct( $this->urlDecoder = $urlDecoder; $this->customerUrl = $customerUrl; $this->resultFactory = $resultFactory; - $this->cookieMetadataFactory = $cookieMetadataFactory; + $this->redirectCookieManager = $redirectCookieManager; $this->hostChecker = $hostChecker ?: ObjectManager::getInstance()->get(HostChecker::class); } @@ -277,7 +280,7 @@ public function setCookieManager($value) */ public function getRedirectCookie() { - return $this->getCookieManager()->getCookie(self::LOGIN_REDIRECT_URL, null); + return $this->redirectCookieManager->getRedirectCookie(); } /** @@ -288,11 +291,7 @@ public function getRedirectCookie() */ public function setRedirectCookie($route) { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setHttpOnly(true) - ->setDuration(3600) - ->setPath($this->storeManager->getStore()->getStorePath()); - $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route, $cookieMetadata); + $this->redirectCookieManager->setRedirectCookie($route, $this->storeManager->getStore()); } /** @@ -302,8 +301,6 @@ public function setRedirectCookie($route) */ public function clearRedirectCookie() { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setPath($this->storeManager->getStore()->getStorePath()); - $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL, $cookieMetadata); + $this->redirectCookieManager->clearRedirectCookie($this->storeManager->getStore()); } } diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php new file mode 100755 index 0000000000000..04c87717fe215 --- /dev/null +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -0,0 +1,72 @@ +cookieMetadataFactory = $cookieMetadataFactory; + $this->cookieManager = $cookieManager; + } + + /** + * {@inheritdoc} + */ + public function getRedirectCookie() + { + return $this->cookieManager->getCookie(self::COOKIE_NAME, null); + } + + /** + * {@inheritdoc} + */ + public function setRedirectCookie($route, StoreInterface $store) + { + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setHttpOnly(true) + ->setDuration(3600) + ->setPath($store->getStorePath()); + $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $route, $cookieMetadata); + } + + /** + * {@inheritdoc} + */ + public function clearRedirectCookie(StoreInterface $store) + { + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setPath($store->getStorePath()); + $this->cookieManager->deleteCookie(self::COOKIE_NAME, $cookieMetadata); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php old mode 100644 new mode 100755 index 0138c6c709b7c..66971bc15d88f --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -8,6 +8,7 @@ namespace Magento\Customer\Test\Unit\Model\Account; +use Magento\Customer\Api\RedirectCookieManagerInterface; use Magento\Customer\Model\Account\Redirect; use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\Controller\ResultFactory; @@ -80,6 +81,11 @@ class RedirectTest extends \PHPUnit\Framework\TestCase */ protected $resultFactory; + /** + * @var RedirectCookieManagerInterface | \PHPUnit_Framework_MockObject_MockObject + */ + protected $redirectCookieManager; + /** * @var HostChecker | \PHPUnit_Framework_MockObject_MockObject */ @@ -139,6 +145,10 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->redirectCookieManager = $this->getMockBuilder(RedirectCookieManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->hostChecker = $this->getMockBuilder(HostChecker::class) ->disableOriginalConstructor() ->getMock(); @@ -155,6 +165,7 @@ protected function setUp() 'urlDecoder' => $this->urlDecoder, 'customerUrl' => $this->customerUrl, 'resultFactory' => $this->resultFactory, + 'redirectCookieManager' => $this->redirectCookieManager, 'hostChecker' => $this->hostChecker, ] ); diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml old mode 100644 new mode 100755 index a181d6dd217fd..6d07814b362c2 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -468,4 +468,7 @@ + From d56f3c6d908634dd71117f713c32cf7f5fa7e045 Mon Sep 17 00:00:00 2001 From: George Babarus Date: Fri, 5 Jul 2019 11:55:36 +0300 Subject: [PATCH 021/666] reduce resetData calls on DeploymentConfig --- .../Model/Logger/Handler/DebugTest.php | 1 + .../Framework/App/DeploymentConfig.php | 39 ++++--- .../App/Test/Unit/DeploymentConfigTest.php | 108 ++++++++++++------ .../Magento/Framework/Module/ModuleList.php | 19 +-- .../Module/Test/Unit/ModuleListTest.php | 8 +- .../ModuleEnableDisableCommandTest.php | 23 ++-- 6 files changed, 124 insertions(+), 74 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php b/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php index f7a47017f8b18..fec71206accd8 100644 --- a/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php +++ b/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php @@ -173,6 +173,7 @@ private function reinitDeploymentConfig() { $this->etcDirectory->delete(self::$configFile); $this->etcDirectory->copyFile(self::$backupFile, self::$configFile); + $this->deploymentConfig->resetData(); } /** diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig.php b/lib/internal/Magento/Framework/App/DeploymentConfig.php index 40b03b068d6ab..ddd7faa80b906 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig.php @@ -7,6 +7,9 @@ namespace Magento\Framework\App; use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\RuntimeException; +use Magento\Framework\Phrase; /** * Application deployment configuration @@ -63,6 +66,8 @@ public function __construct(DeploymentConfig\Reader $reader, $overrideData = []) * @param string $key * @param mixed $defaultValue * @return mixed|null + * @throws FileSystemException + * @throws RuntimeException */ public function get($key = null, $defaultValue = null) { @@ -82,10 +87,11 @@ public function get($key = null, $defaultValue = null) * Checks if data available * * @return bool + * @throws FileSystemException + * @throws RuntimeException */ public function isAvailable() { - $this->data = null; $this->load(); return isset($this->flatData[ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE]); } @@ -95,6 +101,8 @@ public function isAvailable() * * @param string $key * @return null|mixed + * @throws FileSystemException + * @throws RuntimeException */ public function getConfigData($key = null) { @@ -104,11 +112,7 @@ public function getConfigData($key = null) return null; } - if (isset($this->data[$key])) { - return $this->data[$key]; - } - - return $this->data; + return $this->data[$key] ?? $this->data; } /** @@ -125,6 +129,8 @@ public function resetData() * Check if data from deploy files is available * * @return bool + * @throws FileSystemException + * @throws RuntimeException * @since 100.1.3 */ public function isDbAvailable() @@ -137,6 +143,8 @@ public function isDbAvailable() * Loads the configuration data * * @return void + * @throws FileSystemException + * @throws RuntimeException */ private function load() { @@ -158,12 +166,15 @@ private function load() * * @param array $params * @param string $path + * @param array $flattenResult * @return array - * @throws \Exception + * @throws RuntimeException */ - private function flattenParams(array $params, $path = null) + private function flattenParams(array $params, $path = null, array &$flattenResult = null) : array { - $cache = []; + if (null === $flattenResult) { + $flattenResult = []; + } foreach ($params as $key => $param) { if ($path) { @@ -171,15 +182,15 @@ private function flattenParams(array $params, $path = null) } else { $newPath = $key; } - if (isset($cache[$newPath])) { - throw new \Exception("Key collision {$newPath} is already defined."); + if (isset($flattenResult[$newPath])) { + throw new RuntimeException(new Phrase("Key collision '%1' is already defined.", [$newPath])); } - $cache[$newPath] = $param; + $flattenResult[$newPath] = $param; if (is_array($param)) { - $cache = array_merge($cache, $this->flattenParams($param, $newPath)); + $this->flattenParams($param, $newPath, $flattenResult); } } - return $cache; + return $flattenResult; } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfigTest.php index 80ab2302dc91c..81a4f842bdf1d 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfigTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfigTest.php @@ -14,27 +14,33 @@ class DeploymentConfigTest extends \PHPUnit\Framework\TestCase /** * @var array */ - private static $fixture = [ - 'configData1' => 'scalar_value', - 'configData2' => [ - 'foo' => 1, - 'bar' => ['baz' => 2], - ], - ]; + private static $fixture + = [ + 'configData1' => 'scalar_value', + 'configData2' => [ + 'foo' => 1, + 'bar' => ['baz' => 2], + ], + 'configData3' => null, + 'test_override' => 'original', + ]; /** * @var array */ - private static $flattenedFixture = [ - 'configData1' => 'scalar_value', - 'configData2' => [ - 'foo' => 1, - 'bar' => ['baz' => 2], - ], - 'configData2/foo' => 1, - 'configData2/bar' => ['baz' => 2], - 'configData2/bar/baz' => 2, - ]; + private static $flattenedFixture + = [ + 'configData1' => 'scalar_value', + 'configData2' => [ + 'foo' => 1, + 'bar' => ['baz' => 2], + ], + 'configData2/foo' => 1, + 'configData2/bar' => ['baz' => 2], + 'configData2/bar/baz' => 2, + 'configData3' => null, + 'test_override' => 'overridden', + ]; /** * @var array @@ -63,21 +69,24 @@ class DeploymentConfigTest extends \PHPUnit\Framework\TestCase public static function setUpBeforeClass() { - self::$fixtureConfig = require __DIR__ . '/_files/config.php'; - self::$fixtureConfigMerged = require __DIR__ . '/_files/other/local_developer_merged.php'; + self::$fixtureConfig = require __DIR__.'/_files/config.php'; + self::$fixtureConfigMerged = require __DIR__.'/_files/other/local_developer_merged.php'; } protected function setUp() { - $this->reader = $this->createMock(\Magento\Framework\App\DeploymentConfig\Reader::class); - $this->_deploymentConfig = new \Magento\Framework\App\DeploymentConfig($this->reader, []); + $this->reader = $this->createMock(\Magento\Framework\App\DeploymentConfig\Reader::class); + $this->_deploymentConfig = new \Magento\Framework\App\DeploymentConfig( + $this->reader, + ['test_override' => 'overridden'] + ); $this->_deploymentConfigMerged = new \Magento\Framework\App\DeploymentConfig( $this->reader, - require __DIR__ . '/_files/other/local_developer.php' + require __DIR__.'/_files/other/local_developer.php' ); } - public function testGetters() + public function testGetters(): void { $this->reader->expects($this->once())->method('load')->willReturn(self::$fixture); $this->assertSame(self::$flattenedFixture, $this->_deploymentConfig->get()); @@ -85,33 +94,40 @@ public function testGetters() $this->assertSame(self::$flattenedFixture, $this->_deploymentConfig->get()); $this->assertSame('scalar_value', $this->_deploymentConfig->getConfigData('configData1')); $this->assertSame(self::$fixture['configData2'], $this->_deploymentConfig->getConfigData('configData2')); + $this->assertSame(self::$fixture['configData3'], $this->_deploymentConfig->getConfigData('configData3')); + $this->assertSame('', $this->_deploymentConfig->get('configData3')); + $this->assertSame('defaultValue', $this->_deploymentConfig->get('invalid_key', 'defaultValue')); + $this->assertNull($this->_deploymentConfig->getConfigData('invalid_key')); + $this->assertSame('overridden', $this->_deploymentConfig->get('test_override')); } - public function testIsAvailable() + public function testIsAvailable(): void { - $this->reader->expects($this->once())->method('load')->willReturn([ - ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE => 1 - ]); + $this->reader->expects($this->once())->method('load')->willReturn( + [ + ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE => 1, + ] + ); $object = new DeploymentConfig($this->reader); $this->assertTrue($object->isAvailable()); } - public function testNotAvailable() + public function testNotAvailable(): void { $this->reader->expects($this->once())->method('load')->willReturn([]); $object = new DeploymentConfig($this->reader); $this->assertFalse($object->isAvailable()); } - public function testNotAvailableThenAvailable() + /** + * test if the configuration changes during the same request, the configuration remain the same + */ + public function testNotAvailableThenAvailable(): void { - $this->reader->expects($this->at(0))->method('load')->willReturn([]); - $this->reader->expects($this->at(1))->method('load')->willReturn([ - ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE => 1 - ]); + $this->reader->expects($this->once())->method('load')->willReturn([]); $object = new DeploymentConfig($this->reader); $this->assertFalse($object->isAvailable()); - $this->assertTrue($object->isAvailable()); + $this->assertFalse($object->isAvailable()); } /** @@ -120,7 +136,7 @@ public function testNotAvailableThenAvailable() * @expectedExceptionMessage Key collision * @dataProvider keyCollisionDataProvider */ - public function testKeyCollision(array $data) + public function testKeyCollision(array $data): void { $this->reader->expects($this->once())->method('load')->willReturn($data); $object = new DeploymentConfig($this->reader); @@ -130,14 +146,32 @@ public function testKeyCollision(array $data) /** * @return array */ - public function keyCollisionDataProvider() + public function keyCollisionDataProvider(): array { return [ [ ['foo' => ['bar' => '1'], 'foo/bar' => '2'], ['foo/bar' => '1', 'foo' => ['bar' => '2']], ['foo' => ['subfoo' => ['subbar' => '1'], 'subfoo/subbar' => '2'], 'bar' => '3'], - ] + ], ]; } + + public function testResetData(): void + { + $this->reader->expects($this->exactly(2))->method('load')->willReturn(self::$fixture); + $this->assertSame(self::$flattenedFixture, $this->_deploymentConfig->get()); + $this->_deploymentConfig->resetData(); + // second time to ensure loader will be invoked only once after reset + $this->assertSame(self::$flattenedFixture, $this->_deploymentConfig->get()); + $this->assertSame(self::$flattenedFixture, $this->_deploymentConfig->get()); + } + + public function testIsDbAvailable(): void + { + $this->reader->expects($this->exactly(2))->method('load')->willReturnOnConsecutiveCalls([], ['db' => []]); + $this->assertFalse($this->_deploymentConfig->isDbAvailable()); + $this->_deploymentConfig->resetData(); + $this->assertTrue($this->_deploymentConfig->isDbAvailable()); + } } diff --git a/lib/internal/Magento/Framework/Module/ModuleList.php b/lib/internal/Magento/Framework/Module/ModuleList.php index 6ee061cffb3d0..5a60a1c102b05 100644 --- a/lib/internal/Magento/Framework/Module/ModuleList.php +++ b/lib/internal/Magento/Framework/Module/ModuleList.php @@ -59,7 +59,7 @@ public function __construct(DeploymentConfig $config, ModuleList\Loader $loader) } /** - * {@inheritdoc} + * @inheritdoc * * Note that this triggers loading definitions of all existing modules in the system. * Use this method only when you actually need modules' declared meta-information. @@ -84,8 +84,7 @@ public function getAll() } /** - * {@inheritdoc} - * @see has() + * @inheritdoc */ public function getOne($name) { @@ -94,7 +93,7 @@ public function getOne($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function getNames() { @@ -107,7 +106,7 @@ public function getNames() } /** - * {@inheritdoc} + * @inheritdoc */ public function has($name) { @@ -136,12 +135,16 @@ public function isModuleInfoAvailable() * Loads configuration data only * * @return void + * @throws \Magento\Framework\Exception\FileSystemException + * @throws \Magento\Framework\Exception\RuntimeException */ private function loadConfigData() { - $this->config->resetData(); - if (null === $this->configData && null !== $this->config->get(ConfigOptionsListConstants::KEY_MODULES)) { - $this->configData = $this->config->get(ConfigOptionsListConstants::KEY_MODULES); + if (null === $this->configData) { + $this->config->resetData(); + if (null !== $this->config->get(ConfigOptionsListConstants::KEY_MODULES)) { + $this->configData = $this->config->get(ConfigOptionsListConstants::KEY_MODULES); + } } } } diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/ModuleListTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/ModuleListTest.php index 9b4f238725138..3142bbbc6771a 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/ModuleListTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/ModuleListTest.php @@ -47,7 +47,7 @@ protected function setUp() public function testGetAll() { - $this->config->expects($this->exactly(2))->method('resetData'); + $this->config->expects($this->once())->method('resetData'); $this->setLoadAllExpectation(); $this->setLoadConfigExpectation(); $expected = ['foo' => self::$allFixture['foo']]; @@ -65,7 +65,7 @@ public function testGetAllNoData() public function testGetOne() { - $this->config->expects($this->exactly(2))->method('resetData'); + $this->config->expects($this->once())->method('resetData'); $this->setLoadAllExpectation(); $this->setLoadConfigExpectation(); $this->assertSame(['key' => 'value'], $this->model->getOne('foo')); @@ -74,7 +74,7 @@ public function testGetOne() public function testGetNames() { - $this->config->expects($this->exactly(2))->method('resetData'); + $this->config->expects($this->once())->method('resetData'); $this->setLoadAllExpectation(false); $this->setLoadConfigExpectation(); $this->assertSame(['foo'], $this->model->getNames()); @@ -83,7 +83,7 @@ public function testGetNames() public function testHas() { - $this->config->expects($this->exactly(2))->method('resetData'); + $this->config->expects($this->once())->method('resetData'); $this->setLoadAllExpectation(false); $this->setLoadConfigExpectation(); $this->assertTrue($this->model->has('foo')); diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleEnableDisableCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleEnableDisableCommandTest.php index 4ff2b0c7bca58..8eb13a9c1ec5e 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleEnableDisableCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleEnableDisableCommandTest.php @@ -53,23 +53,24 @@ protected function setUp() { $this->objectManagerProviderMock = $this->createMock(\Magento\Setup\Model\ObjectManagerProvider::class); $objectManager = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class); - $this->objectManagerProviderMock->expects($this->any()) + $this->objectManagerProviderMock ->method('get') - ->will($this->returnValue($objectManager)); + ->willReturn($objectManager); $this->statusMock = $this->createMock(\Magento\Framework\Module\Status::class); $this->cacheMock = $this->createMock(\Magento\Framework\App\Cache::class); $this->cleanupFilesMock = $this->createMock(\Magento\Framework\App\State\CleanupFiles::class); $this->fullModuleListMock = $this->createMock(\Magento\Framework\Module\FullModuleList::class); $this->deploymentConfigMock = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->generatedFiles = $this->createMock(\Magento\Framework\Code\GeneratedFiles::class); - $objectManager->expects($this->any()) - ->method('get') - ->will($this->returnValueMap([ - [\Magento\Framework\Module\Status::class, $this->statusMock], - [\Magento\Framework\App\Cache::class, $this->cacheMock], - [\Magento\Framework\App\State\CleanupFiles::class, $this->cleanupFilesMock], - [\Magento\Framework\Module\FullModuleList::class, $this->fullModuleListMock], - ])); + $objectManager->method('get') + ->willReturnMap( + [ + [\Magento\Framework\Module\Status::class, $this->statusMock], + [\Magento\Framework\App\Cache::class, $this->cacheMock], + [\Magento\Framework\App\State\CleanupFiles::class, $this->cleanupFilesMock], + [\Magento\Framework\Module\FullModuleList::class, $this->fullModuleListMock], + ] + ); } /** @@ -189,7 +190,7 @@ public function testExecuteAll($isEnable, $expectedMessage) if ($isEnable) { $this->deploymentConfigMock->expects($this->once()) ->method('isAvailable') - ->willReturn(['Magento_Module1']); + ->willReturn(true); } else { $this->deploymentConfigMock->expects($this->never()) ->method('isAvailable'); From 2769f7c8d8caa58fab0f1e6c6f27879859d1b573 Mon Sep 17 00:00:00 2001 From: Jens Scherbl Date: Sun, 22 Sep 2019 15:13:39 +0200 Subject: [PATCH 022/666] Allows additional payment checks in payment method list --- app/code/Magento/Payment/Model/MethodList.php | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Payment/Model/MethodList.php b/app/code/Magento/Payment/Model/MethodList.php index 5a426d72e4cfd..e5b961f87e426 100644 --- a/app/code/Magento/Payment/Model/MethodList.php +++ b/app/code/Magento/Payment/Model/MethodList.php @@ -39,16 +39,24 @@ class MethodList */ private $paymentMethodInstanceFactory; + /** + * @var array + */ + private $additionalChecks; + /** * @param \Magento\Payment\Helper\Data $paymentHelper - * @param Checks\SpecificationFactory $specificationFactory + * @param Checks\SpecificationFactory $specificationFactory + * @param array $additionalChecks */ public function __construct( \Magento\Payment\Helper\Data $paymentHelper, - \Magento\Payment\Model\Checks\SpecificationFactory $specificationFactory + \Magento\Payment\Model\Checks\SpecificationFactory $specificationFactory, + array $additionalChecks = [] ) { $this->paymentHelper = $paymentHelper; $this->methodSpecificationFactory = $specificationFactory; + $this->additionalChecks = $additionalChecks; } /** @@ -80,12 +88,15 @@ public function getAvailableMethods(\Magento\Quote\Api\Data\CartInterface $quote protected function _canUseMethod($method, \Magento\Quote\Api\Data\CartInterface $quote) { return $this->methodSpecificationFactory->create( - [ - AbstractMethod::CHECK_USE_CHECKOUT, - AbstractMethod::CHECK_USE_FOR_COUNTRY, - AbstractMethod::CHECK_USE_FOR_CURRENCY, - AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, - ] + array_merge( + [ + AbstractMethod::CHECK_USE_CHECKOUT, + AbstractMethod::CHECK_USE_FOR_COUNTRY, + AbstractMethod::CHECK_USE_FOR_CURRENCY, + AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX, + ], + $this->additionalChecks + ) )->isApplicable( $method, $quote From 882868a5c33712691a79f62dfdf05459427cc31d Mon Sep 17 00:00:00 2001 From: Jens Scherbl Date: Sun, 22 Sep 2019 16:34:48 +0200 Subject: [PATCH 023/666] Fixes unrelated code style issues --- app/code/Magento/Payment/Model/MethodList.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Payment/Model/MethodList.php b/app/code/Magento/Payment/Model/MethodList.php index e5b961f87e426..746306cbd0bbf 100644 --- a/app/code/Magento/Payment/Model/MethodList.php +++ b/app/code/Magento/Payment/Model/MethodList.php @@ -60,6 +60,8 @@ public function __construct( } /** + * Returns all available payment methods for the given quote. + * * @param \Magento\Quote\Api\Data\CartInterface $quote * @return \Magento\Payment\Model\MethodInterface[] */ From 504dd9144be469897baf834e58ae057537a07288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 3 Oct 2019 15:55:56 +0200 Subject: [PATCH 024/666] Issue #24842: Unable to delete custom option file in admin order create Fix inputBox selector to match html structure --- .../catalog/product/composite/fieldset/options/type/file.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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=""]')[0]; this.inputFileAction = inputBox.select('input[name=""]')[0]; - this.fileNameBox = inputBox.up('dd').select('.')[0]; + this.fileNameBox = inputBox.up('div').select('.')[0]; }, toggleFileChange: function(inputBox) { From 91d61bdc5e5b85dcc5b51f7b539055e187a16790 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 24 Sep 2019 17:01:57 +0300 Subject: [PATCH 025/666] magento/magento2#24460: Multiline custom attributes save fix. --- .../Model/Address/AbstractAddress.php | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 158461b4d9c17..fb067decd0b37 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -281,7 +281,13 @@ public function setData($key, $value = null) $key = $this->_implodeArrayField($key); } elseif (is_array($value) && $this->isAddressMultilineAttribute($key)) { $value = $this->_implodeArrayValues($value); + } elseif (self::CUSTOM_ATTRIBUTES === $key && is_array($value)) { + foreach ($value as &$attribute) { + $attribute = is_array($attribute) ? $attribute : $attribute->__toArray(); + $attribute = $this->processCustomAttribute($attribute); + } } + return parent::setData($key, $value); } @@ -637,8 +643,8 @@ public function unsRegion() * Is company required * * @return bool - * @since 100.2.0 * @throws \Magento\Framework\Exception\LocalizedException + * @since 100.2.0 */ protected function isCompanyRequired() { @@ -649,8 +655,8 @@ protected function isCompanyRequired() * Is telephone required * * @return bool - * @since 100.2.0 * @throws \Magento\Framework\Exception\LocalizedException + * @since 100.2.0 */ protected function isTelephoneRequired() { @@ -661,11 +667,30 @@ protected function isTelephoneRequired() * Is fax required * * @return bool - * @since 100.2.0 * @throws \Magento\Framework\Exception\LocalizedException + * @since 100.2.0 */ protected function isFaxRequired() { return ($this->_eavConfig->getAttribute('customer_address', 'fax')->getIsRequired()); } + + /** + * Unify attribute format. + * + * @param array $attribute + * @return array + */ + private function processCustomAttribute(array $attribute): array + { + if (isset($attribute['attribute_code']) && + isset($attribute['value']) && + is_array($attribute['value']) && + $this->isAddressMultilineAttribute($attribute['attribute_code']) + ) { + $attribute['value'] = $this->_implodeArrayValues($attribute['value']); + } + + return $attribute; + } } From 6458cc851791e1c3e38ffa3d5410fa111278e156 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Mon, 7 Oct 2019 13:44:39 +0300 Subject: [PATCH 026/666] magento/magento2#22296: Integration test fix. --- .../Magento/Catalog/Model/Product/UrlTest.php | 2 +- .../Magento/Store/Model/StoreTest.php | 36 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) 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 663ee986bca3b..b1001a6afb14f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php @@ -49,7 +49,7 @@ 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 + * @magentoDbIsolation enabled * @dataProvider getUrlsWithSecondStoreProvider * @magentoAppArea adminhtml */ diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 00de5544d8fb7..4a670f39f4e01 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -176,11 +176,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'); @@ -283,7 +285,7 @@ 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 @@ -318,7 +320,7 @@ public function testGetCurrentUrl() /** * @magentoDataFixture Magento/Store/_files/second_store.php * @magentoDataFixture Magento/Catalog/_files/category_product.php - * @magentoDbIsolation disabled + * @magentoDbIsolation enabled */ public function testGetCurrentUrlWithUseStoreInUrlFalse() { @@ -366,14 +368,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'], @@ -446,8 +450,8 @@ public function testIsUseStoreInUrl($storeInUrl, $disableStoreInUrl, $expectedRe } /** - * @see self::testIsUseStoreInUrl; * @return array + * @see self::testIsUseStoreInUrl; */ public function isUseStoreInUrlDataProvider() { From 5188efdbcfe31e02147d2fc6846ffd5d40e4d0ca Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 15:40:39 -0400 Subject: [PATCH 027/666] Test Fixes --- .../Customer/Model/Account/Redirect.php | 3 ++ .../Customer/Model/RedirectCookieManager.php | 5 +++ .../Test/Unit/Model/Account/RedirectTest.php | 32 ++++++++++--------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index c2e66e30b685f..f3985b5b92959 100755 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -24,6 +24,8 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + * */ class Redirect { @@ -89,6 +91,7 @@ class Redirect private $session; /** + * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @param RequestInterface $request * @param Session $customerSession * @param ScopeConfigInterface $scopeConfig diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php index 04c87717fe215..aefdf51bd776a 100755 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -11,6 +11,11 @@ use Magento\Store\Api\Data\StoreInterface; use Magento\Customer\Api\RedirectCookieManagerInterface; +/** + * Customer redirect cookie manager + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + * + */ class RedirectCookieManager implements RedirectCookieManagerInterface { /** 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 66971bc15d88f..204babe62491c 100755 --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -97,21 +97,23 @@ protected function setUp() $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); From 3cf8f224a3f850aa0838b700ba390eb25fd1f704 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 15:46:27 -0400 Subject: [PATCH 028/666] Signed CLA From 75970034babbf4525a2ccf5bf4ecfbe4d55fa897 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 16:26:10 -0400 Subject: [PATCH 029/666] Fixed Code Style Issues --- .../Api/RedirectCookieManagerInterface.php | 41 ------------------- .../Customer/Model/Account/Redirect.php | 13 +++--- .../Customer/Model/RedirectCookieManager.php | 18 +++++--- app/code/Magento/Customer/etc/di.xml | 3 -- 4 files changed, 20 insertions(+), 55 deletions(-) delete mode 100755 app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php diff --git a/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php b/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php deleted file mode 100755 index 5f4f1f6f917de..0000000000000 --- a/app/code/Magento/Customer/Api/RedirectCookieManagerInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -request = $request; @@ -254,6 +255,7 @@ private function applyRedirect($url) * Get Cookie manager. For release backward compatibility. * * @deprecated 100.0.10 + * @see \Magento\Customer\Model\RedirectCookieManager * @return CookieManagerInterface */ protected function getCookieManager() @@ -268,6 +270,7 @@ protected function getCookieManager() * Set cookie manager. For unit tests. * * @deprecated 100.0.10 + * @see \Magento\Customer\Model\RedirectCookieManager * @param object $value * @return void */ diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php index aefdf51bd776a..61b8282ff8378 100755 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -18,9 +18,6 @@ */ class RedirectCookieManager implements RedirectCookieManagerInterface { - /** - * Cookie name - */ const COOKIE_NAME = 'login_redirect'; /** @@ -46,7 +43,9 @@ public function __construct( } /** - * {@inheritdoc} + * Get redirect route from cookie for case of successful login/registration + * + * @return null|string */ public function getRedirectCookie() { @@ -54,7 +53,11 @@ public function getRedirectCookie() } /** - * {@inheritdoc} + * Save redirect route to cookie for case of successful login/registration + * + * @param string $route + * @param StoreInterface $store + * @return void */ public function setRedirectCookie($route, StoreInterface $store) { @@ -66,7 +69,10 @@ public function setRedirectCookie($route, StoreInterface $store) } /** - * {@inheritdoc} + * Clear cookie with requested route + * + * @param StoreInterface $store + * @return void */ public function clearRedirectCookie(StoreInterface $store) { diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index 6d07814b362c2..a181d6dd217fd 100755 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -468,7 +468,4 @@ - From 94138920f8c54365bc29f72b63b3a2de9c04a0a0 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 16:35:28 -0400 Subject: [PATCH 030/666] Unit Tests Fix --- .../Customer/Test/Unit/Model/Account/RedirectTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 204babe62491c..5efef491adae1 100755 --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -8,7 +8,7 @@ namespace Magento\Customer\Test\Unit\Model\Account; -use Magento\Customer\Api\RedirectCookieManagerInterface; +use Magento\Customer\Model\RedirectCookieManager; use Magento\Customer\Model\Account\Redirect; use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\Controller\ResultFactory; @@ -82,7 +82,7 @@ class RedirectTest extends \PHPUnit\Framework\TestCase protected $resultFactory; /** - * @var RedirectCookieManagerInterface | \PHPUnit_Framework_MockObject_MockObject + * @var RedirectCookieManager | \PHPUnit_Framework_MockObject_MockObject */ protected $redirectCookieManager; @@ -147,7 +147,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->redirectCookieManager = $this->getMockBuilder(RedirectCookieManagerInterface::class) + $this->redirectCookieManager = $this->getMockBuilder(RedirectCookieManager::class) ->disableOriginalConstructor() ->getMock(); From 9f2bbc2c0060ce884c186a627403c1296080fe2d Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 16:49:09 -0400 Subject: [PATCH 031/666] Interface removed --- app/code/Magento/Customer/Model/RedirectCookieManager.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php index 61b8282ff8378..28c85a7f1a9a1 100755 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -9,14 +9,13 @@ use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; use Magento\Framework\Stdlib\CookieManagerInterface; use Magento\Store\Api\Data\StoreInterface; -use Magento\Customer\Api\RedirectCookieManagerInterface; /** * Customer redirect cookie manager * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * */ -class RedirectCookieManager implements RedirectCookieManagerInterface +class RedirectCookieManager { const COOKIE_NAME = 'login_redirect'; From bfa636f75b220e3a59cb168ccc79b6ccdb055e07 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 17:10:32 -0400 Subject: [PATCH 032/666] Code Style --- app/code/Magento/Customer/Model/RedirectCookieManager.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php index 28c85a7f1a9a1..79ca50e14e38a 100755 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -13,7 +13,6 @@ /** * Customer redirect cookie manager * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) - * */ class RedirectCookieManager { From 6446aed759f9ed44c1fecde4632e14f786b3117a Mon Sep 17 00:00:00 2001 From: Alex Lukyanau Date: Tue, 8 Oct 2019 17:50:06 -0400 Subject: [PATCH 033/666] Current file(s) contain protected modifier for method or property. (phpProtectedModifier) --- app/code/Magento/Customer/Model/RedirectCookieManager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php index 79ca50e14e38a..27a6be6671f30 100755 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ b/app/code/Magento/Customer/Model/RedirectCookieManager.php @@ -21,12 +21,12 @@ class RedirectCookieManager /** * @var CookieMetadataFactory */ - protected $cookieMetadataFactory; + private $cookieMetadataFactory; /** * @var CookieManagerInterface */ - protected $cookieManager; + private $cookieManager; /** * @param CookieMetadataFactory $cookieMetadataFactory From 4c23a16eb20505a61edf317a1f6e75307aa6c05f Mon Sep 17 00:00:00 2001 From: Artem Voloznov Date: Fri, 11 Oct 2019 11:12:16 +0300 Subject: [PATCH 034/666] Fix doc block for Magento\Framework\MessageQueue\Topology\Config --- .../Magento/Framework/MessageQueue/Topology/Config.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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() { From 6b3bd36cb4fda9a9f162f123932c6b9f93291ae9 Mon Sep 17 00:00:00 2001 From: "vishalverma.magento279" Date: Wed, 23 Oct 2019 21:02:10 +0530 Subject: [PATCH 035/666] #25245 fixed --- app/code/Magento/Search/Block/Term.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index b27ef6b01fda2..6dab372df3edc 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -99,6 +99,9 @@ protected function _loadTerms() $temp[$term->getQueryText()] = $term; $termKeys[] = $term->getQueryText(); } + if (empty($termKeys)) { + return $this; + } natcasesort($termKeys); foreach ($termKeys as $termKey) { From c5eb6233e693c9ae7178aff6d1580d372e40c059 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Tue, 22 Oct 2019 20:22:26 +0300 Subject: [PATCH 036/666] upgrade method delete by ids to inject array skus --- .../Api/CategoryLinkRepositoryInterface.php | 15 +++++- .../Catalog/Model/CategoryLinkManagement.php | 2 +- .../Catalog/Model/CategoryLinkRepository.php | 46 ++++++++++++++++++- .../Unit/Model/CategoryLinkRepositoryTest.php | 4 +- app/code/Magento/Catalog/etc/webapi.xml | 2 +- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php index a65355c690923..b4f5b6472661a 100644 --- a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php @@ -36,6 +36,19 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink); + /** + * Remove the product assignment from the category by category id and array of sku + * + * @param int $categoryId + * @param array $sku + * @return bool will returned True if products successfully deleted + * + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\StateException + * @throws \Magento\Framework\Exception\InputException + */ + public function deleteByIds($categoryId, $sku); + /** * Remove the product assignment from the category by category id and sku * @@ -47,5 +60,5 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\InputException */ - public function deleteByIds($categoryId, $sku); + public function deleteById($categoryId, $sku); } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index 8966848a6d036..103cc0970603b 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -93,7 +93,7 @@ public function assignProductToCategories($productSku, array $categoryIds) $product = $this->getProductRepository()->get($productSku); $assignedCategories = $this->getProductResource()->getCategoryIds($product); foreach (array_diff($assignedCategories, $categoryIds) as $categoryId) { - $this->getCategoryLinkRepository()->deleteByIds($categoryId, $productSku); + $this->getCategoryLinkRepository()->deleteById($categoryId, $productSku); } foreach (array_diff($categoryIds, $assignedCategories) as $categoryId) { diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index fb0ea680569a8..b7d7d09a9a0e6 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -21,16 +21,24 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit */ protected $productRepository; + /** + * @var \Magento\Catalog\Model\ResourceModel\Product + */ + private $productResource; + /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, + \Magento\Catalog\Model\ResourceModel\Product $productResource ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; + $this->productResource = $productResource; } /** @@ -64,13 +72,47 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { - return $this->deleteByIds($productLink->getCategoryId(), $productLink->getSku()); + return $this->deleteById($productLink->getCategoryId(), $productLink->getSku()); } /** * {@inheritdoc} */ public function deleteByIds($categoryId, $sku) + { + $category = $this->categoryRepository->get($categoryId); + $products = $this->productResource->getProductsIdsBySkus($sku); + + $productPositions = $category->getProductsPosition(); + + foreach ($products as $productSku => $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(',', $sku), + "category" => $category->getId() + ] + ), + $e + ); + } + return true; + } + + /** + * {@inheritDoc} + */ + public function deleteById($categoryId, $sku) { $category = $this->categoryRepository->get($categoryId); $product = $this->productRepository->get($sku); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index b42262f1f0384..1af8669bbc9fb 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -113,7 +113,7 @@ 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)); + $this->assertTrue($this->model->deleteById($categoryId, $productSku)); } /** @@ -140,7 +140,7 @@ 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->model->deleteByIds($categoryId, $productSku); + $this->model->deleteById($categoryId, $productSku); } /** diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index 3f82175ab02eb..a001aed3c7e5f 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -457,7 +457,7 @@ - + From 3558184bca391cf790aebaf20d3b61bf2b90b842 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev Date: Wed, 23 Oct 2019 23:49:18 +0300 Subject: [PATCH 037/666] refactor getByIds method and use object manager into constructor class --- .../Api/CategoryLinkRepositoryInterface.php | 17 +------ .../Catalog/Model/CategoryLinkManagement.php | 2 +- .../Catalog/Model/CategoryLinkRepository.php | 50 ++++--------------- .../Unit/Model/CategoryLinkRepositoryTest.php | 4 +- app/code/Magento/Catalog/etc/webapi.xml | 2 +- 5 files changed, 16 insertions(+), 59 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php index b4f5b6472661a..2d14f11d05d31 100644 --- a/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryLinkRepositoryInterface.php @@ -37,10 +37,10 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink); /** - * Remove the product assignment from the category by category id and array of sku + * Remove the product assignment from the category by category id and array or string of sku * * @param int $categoryId - * @param array $sku + * @param string|array $sku * @return bool will returned True if products successfully deleted * * @throws \Magento\Framework\Exception\CouldNotSaveException @@ -48,17 +48,4 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p * @throws \Magento\Framework\Exception\InputException */ public function deleteByIds($categoryId, $sku); - - /** - * Remove the product assignment from the category by category id and sku - * - * @param int $categoryId - * @param string $sku - * @return bool will returned True if products successfully deleted - * - * @throws \Magento\Framework\Exception\CouldNotSaveException - * @throws \Magento\Framework\Exception\StateException - * @throws \Magento\Framework\Exception\InputException - */ - public function deleteById($categoryId, $sku); } diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index 103cc0970603b..8966848a6d036 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -93,7 +93,7 @@ public function assignProductToCategories($productSku, array $categoryIds) $product = $this->getProductRepository()->get($productSku); $assignedCategories = $this->getProductResource()->getCategoryIds($product); foreach (array_diff($assignedCategories, $categoryIds) as $categoryId) { - $this->getCategoryLinkRepository()->deleteById($categoryId, $productSku); + $this->getCategoryLinkRepository()->deleteByIds($categoryId, $productSku); } foreach (array_diff($categoryIds, $assignedCategories) as $categoryId) { diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index b7d7d09a9a0e6..580fe288b1ee7 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -29,16 +29,14 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\ResourceModel\Product $productResource + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = $productResource; + $this->productResource = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); } /** @@ -72,7 +70,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { - return $this->deleteById($productLink->getCategoryId(), $productLink->getSku()); + return $this->deleteByIds($productLink->getCategoryId(), $productLink->getSku()); } /** @@ -80,9 +78,16 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p */ public function deleteByIds($categoryId, $sku) { + if (!is_array($sku)) { + $sku = [$sku]; + } $category = $this->categoryRepository->get($categoryId); $products = $this->productResource->getProductsIdsBySkus($sku); + if (!$products) { + throw new InputException(__("The category doesn't contain the specified products.")); + } + $productPositions = $category->getProductsPosition(); foreach ($products as $productSku => $productId) { @@ -108,39 +113,4 @@ public function deleteByIds($categoryId, $sku) } return true; } - - /** - * {@inheritDoc} - */ - public function deleteById($categoryId, $sku) - { - $category = $this->categoryRepository->get($categoryId); - $product = $this->productRepository->get($sku); - $productPositions = $category->getProductsPosition(); - - $productID = $product->getId(); - if (!isset($productPositions[$productID])) { - throw new InputException(__("The category doesn't contain the specified product.")); - } - $backupPosition = $productPositions[$productID]; - unset($productPositions[$productID]); - - $category->setPostedProducts($productPositions); - try { - $category->save(); - } catch (\Exception $e) { - throw new CouldNotSaveException( - __( - 'Could not save product "%product" with position %position to category %category', - [ - "product" => $product->getId(), - "position" => $backupPosition, - "category" => $category->getId() - ] - ), - $e - ); - } - return true; - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 1af8669bbc9fb..b42262f1f0384 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -113,7 +113,7 @@ 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->deleteById($categoryId, $productSku)); + $this->assertTrue($this->model->deleteByIds($categoryId, $productSku)); } /** @@ -140,7 +140,7 @@ 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->model->deleteById($categoryId, $productSku); + $this->model->deleteByIds($categoryId, $productSku); } /** diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index a001aed3c7e5f..3f82175ab02eb 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -457,7 +457,7 @@ - + From 738792efa1feb761dc4e9d5b6d8da3f7298db33c Mon Sep 17 00:00:00 2001 From: Andrey Nikolaev Date: Fri, 25 Oct 2019 08:51:32 +0300 Subject: [PATCH 038/666] Add lib wrapper for UUID validation. --- app/etc/di.xml | 1 + .../DataObject/IdentityValidator.php | 23 +++++++++++++++++++ .../DataObject/IdentityValidatorInterface.php | 21 +++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 lib/internal/Magento/Framework/DataObject/IdentityValidator.php create mode 100644 lib/internal/Magento/Framework/DataObject/IdentityValidatorInterface.php diff --git a/app/etc/di.xml b/app/etc/di.xml index f8818de2af842..27b85f0a924c0 100644 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -167,6 +167,7 @@ + diff --git a/lib/internal/Magento/Framework/DataObject/IdentityValidator.php b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php new file mode 100644 index 0000000000000..0aeb16dfbd9bd --- /dev/null +++ b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php @@ -0,0 +1,23 @@ + Date: Sat, 26 Oct 2019 17:08:33 +0300 Subject: [PATCH 039/666] add constructor parameter --- app/code/Magento/Catalog/Model/CategoryLinkRepository.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index 580fe288b1ee7..a109a5bf6582e 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -29,14 +29,16 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + * @param \Magento\Catalog\Model\ResourceModel\Product $productResource */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, + \Magento\Catalog\Model\ResourceModel\Product $productResource = null ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); + $this->productResource = $productResource ?? \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); } /** From 6bf9b7a2e1371654647fd912b53baacc5b4dc161 Mon Sep 17 00:00:00 2001 From: Andrey Nikolaev Date: Sun, 27 Oct 2019 12:39:20 +0300 Subject: [PATCH 040/666] Declare strict types --- .../Magento/Framework/DataObject/IdentityValidator.php | 4 +++- .../Framework/DataObject/IdentityValidatorInterface.php | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/DataObject/IdentityValidator.php b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php index 0aeb16dfbd9bd..b17e04585531a 100644 --- a/lib/internal/Magento/Framework/DataObject/IdentityValidator.php +++ b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Framework\DataObject; use Ramsey\Uuid\Uuid; @@ -15,7 +17,7 @@ class IdentityValidator implements IdentityValidatorInterface /** * @inheritDoc */ - public function isValid($value) + public function isValid(string $value): bool { $isValid = Uuid::isValid($value); return $isValid; diff --git a/lib/internal/Magento/Framework/DataObject/IdentityValidatorInterface.php b/lib/internal/Magento/Framework/DataObject/IdentityValidatorInterface.php index fd8b835665baf..a1979721f0cc9 100644 --- a/lib/internal/Magento/Framework/DataObject/IdentityValidatorInterface.php +++ b/lib/internal/Magento/Framework/DataObject/IdentityValidatorInterface.php @@ -15,7 +15,7 @@ interface IdentityValidatorInterface * * @param string $value * - * @return string + * @return bool */ - public function isValid($value); + public function isValid(string $value): bool; } From bf87df0b47014a7c083ff8fd4a3f6b4e0c157a61 Mon Sep 17 00:00:00 2001 From: Andrey Nikolaev Date: Sun, 27 Oct 2019 17:59:07 +0300 Subject: [PATCH 041/666] Cover identity validator with integration tests --- .../DataObject/IdentityValidatorTest.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/DataObject/IdentityValidatorTest.php diff --git a/dev/tests/integration/testsuite/Magento/Framework/DataObject/IdentityValidatorTest.php b/dev/tests/integration/testsuite/Magento/Framework/DataObject/IdentityValidatorTest.php new file mode 100644 index 0000000000000..15f54ba01a795 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/DataObject/IdentityValidatorTest.php @@ -0,0 +1,41 @@ +identityValidator = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(IdentityValidator::class); + } + + public function testIsValid() + { + $isValid = $this->identityValidator->isValid(self::VALID_UUID); + $this->assertEquals(true, $isValid); + } + + public function testIsNotValid() + { + $isValid = $this->identityValidator->isValid(self::INVALID_UUID); + $this->assertEquals(false, $isValid); + } + + public function testEmptyValue() + { + $isValid = $this->identityValidator->isValid(''); + $this->assertEquals(false, $isValid); + } +} From 5a6cf6feaf58d9a5e1c0b4398a008ee832b50b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Corr=C3=AAa=20Gomes?= Date: Sun, 27 Oct 2019 12:11:46 -0300 Subject: [PATCH 042/666] Contact Page > Changing input phone type to tel --- app/code/Magento/Contact/view/frontend/templates/form.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Contact/view/frontend/templates/form.phtml b/app/code/Magento/Contact/view/frontend/templates/form.phtml index d64a991bcafad..1d0e767022049 100644 --- a/app/code/Magento/Contact/view/frontend/templates/form.phtml +++ b/app/code/Magento/Contact/view/frontend/templates/form.phtml @@ -31,7 +31,7 @@
- +
From 1a9efbeaf122d5fea2c7d301180fc55f62eb4c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Corr=C3=AAa=20Gomes?= Date: Sun, 27 Oct 2019 12:34:36 -0300 Subject: [PATCH 043/666] Customer Widget > Changing input phone type to tel --- .../Customer/view/frontend/templates/widget/telephone.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6367bf10bbade..a8660a8f35121 100644 --- a/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/widget/telephone.phtml @@ -22,7 +22,7 @@ ->getAttributeValidationClass('telephone') ); ?> - Date: Sun, 27 Oct 2019 12:36:01 -0300 Subject: [PATCH 044/666] Report page > Changing input phone type to tel --- pub/errors/default/report.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@
- +
From b6bd937a8276924191c8bf753889941636cecd2d Mon Sep 17 00:00:00 2001 From: Raul Verdugo Date: Sun, 27 Oct 2019 16:56:56 +0100 Subject: [PATCH 045/666] #13865 create a popup to advice about navigator blocked cookies --- .../frontend/layout/default_head_blocks.xml | 1 + .../Theme/view/frontend/requirejs-config.js | 3 +- .../frontend/templates/js/cookie_status.phtml | 20 ++++++++++ .../view/frontend/web/js/cookie-status.js | 38 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml create mode 100644 app/code/Magento/Theme/view/frontend/web/js/cookie-status.js diff --git a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml index ab4dabfa6d1a0..a4a10ef3f6ee9 100644 --- a/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml +++ b/app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml @@ -23,6 +23,7 @@ + diff --git a/app/code/Magento/Theme/view/frontend/requirejs-config.js b/app/code/Magento/Theme/view/frontend/requirejs-config.js index c41a0602ef3e8..b5ffd358c893b 100644 --- a/app/code/Magento/Theme/view/frontend/requirejs-config.js +++ b/app/code/Magento/Theme/view/frontend/requirejs-config.js @@ -30,7 +30,8 @@ var config = { 'welcome': 'Magento_Theme/js/view/welcome', 'breadcrumbs': 'Magento_Theme/js/view/breadcrumbs', 'criticalCssLoader': 'Magento_Theme/js/view/critical-css-loader', - 'jquery/ui': 'jquery/compat' + 'jquery/ui': 'jquery/compat', + 'cookieStatus': 'Magento_Theme/js/cookie-status' } }, deps: [ diff --git a/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml b/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml new file mode 100644 index 0000000000000..833daf43a4570 --- /dev/null +++ b/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js new file mode 100644 index 0000000000000..f736d4366440c --- /dev/null +++ b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js @@ -0,0 +1,38 @@ +define([ + 'jquery', + 'mage/translate', + 'Magento_Ui/js/modal/modal' +], function($, $tr, modal){ + 'use strict'; + + $.widget('mage.cookieStatus', { + /** + * Init object + * @private + */ + _init: function () { + + if(!navigator.cookieEnabled) { + console.log('popup'); + + const options = { + type: 'popup', + responsive: true, + innerScroll: true, + autoOpen: true, + buttons: [{ + text: $.mage.__('Close'), + class: 'cookie-status', + click: function () { + this.closeModal(); + } + }] + }; + + modal(options, $('#cookie-status')); + } + } + }); + + return $.mage.cookieStatus; +}); \ No newline at end of file From 7e527d8706a4590075219fb10080e009d8da3422 Mon Sep 17 00:00:00 2001 From: Raul Verdugo Date: Sun, 27 Oct 2019 17:01:15 +0100 Subject: [PATCH 046/666] #13865 remove console log --- app/code/Magento/Theme/view/frontend/web/js/cookie-status.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js index f736d4366440c..20090bc67befc 100644 --- a/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js +++ b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js @@ -13,8 +13,6 @@ define([ _init: function () { if(!navigator.cookieEnabled) { - console.log('popup'); - const options = { type: 'popup', responsive: true, From 60117ee2523187a546cf0aee5b1c4d1ef8ee49b8 Mon Sep 17 00:00:00 2001 From: Raul Verdugo Date: Tue, 29 Oct 2019 12:53:51 +0100 Subject: [PATCH 047/666] #13865 add scapeHtml to popup text --- .../Theme/view/frontend/templates/js/cookie_status.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml b/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml index 833daf43a4570..2da71c90b5657 100644 --- a/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/js/cookie_status.phtml @@ -6,7 +6,7 @@ ?> 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..c58bcdf5108cb 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 @@ -62,7 +62,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); } diff --git a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php index 0e92bbbab4259..dc8d71ba867c9 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/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/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php index dc9a51b30cfea..e816533d59088 100644 --- a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php @@ -40,11 +40,11 @@ protected function setUp() public function testGetOrder() { - $this->assertSame($this->orderMock, $this->model->getOrder()) ; + $this->assertSame($this->orderMock, $this->model->getOrder()); } public function testGetPayment() { - $this->assertSame($this->paymentMock, $this->model->getPayment()) ; + $this->assertSame($this->paymentMock, $this->model->getPayment()); } } 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..896879c4f67c6 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() { @@ -58,7 +58,7 @@ public function aroundUpdateDataProvider() [10, 20, 'once'], [null, 10, 'never'], [10, 10, 'never'], - [10, 10, 'once', true], + [10, 10, 'once', true] ]; } } 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/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, '
'); From 399fe8eb8f463bf85702e10e0c81c8cfe99a2abf Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare Date: Fri, 10 Jan 2020 17:18:20 +0530 Subject: [PATCH 146/666] model xml issues fixed --- app/code/Magento/AdvancedPricingImportExport/etc/module.xml | 2 +- app/code/Magento/Dhl/etc/module.xml | 2 +- app/code/Magento/Rss/etc/module.xml | 2 +- app/code/Magento/Translation/etc/module.xml | 2 +- app/code/Magento/Ups/etc/module.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 4482ba7a0a5e8..ac7e6f860382b 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index c8f63d08f87a5..e46bb72ad7b3c 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Rss/etc/module.xml b/app/code/Magento/Rss/etc/module.xml index eb56eef3d526f..c00b53e716230 100644 --- a/app/code/Magento/Rss/etc/module.xml +++ b/app/code/Magento/Rss/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Translation/etc/module.xml b/app/code/Magento/Translation/etc/module.xml index f3f146b65416c..5bf40ec19b6e2 100644 --- a/app/code/Magento/Translation/etc/module.xml +++ b/app/code/Magento/Translation/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + diff --git a/app/code/Magento/Ups/etc/module.xml b/app/code/Magento/Ups/etc/module.xml index 70cf0bc5ae98a..1c449f6b1cdb5 100644 --- a/app/code/Magento/Ups/etc/module.xml +++ b/app/code/Magento/Ups/etc/module.xml @@ -6,5 +6,5 @@ */ --> - + From 8273d77d778cbff64ac35dfb14a2181a9112799d Mon Sep 17 00:00:00 2001 From: Lyzun Oleksandr Date: Fri, 10 Jan 2020 16:10:33 +0100 Subject: [PATCH 147/666] Add Class description --- lib/internal/Magento/Framework/DataObject/IdentityValidator.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/internal/Magento/Framework/DataObject/IdentityValidator.php b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php index b17e04585531a..e8c068a093cb5 100644 --- a/lib/internal/Magento/Framework/DataObject/IdentityValidator.php +++ b/lib/internal/Magento/Framework/DataObject/IdentityValidator.php @@ -11,6 +11,8 @@ /** * Class IdentityValidator + * + * Class for validating Uuid's */ class IdentityValidator implements IdentityValidatorInterface { From 638ccd5bde4ff0d966231cb22c232270a2f2e706 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra Date: Fri, 10 Jan 2020 18:45:01 +0200 Subject: [PATCH 148/666] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- ...tomerOrderMatchesGrandTotalActionGroup.xml | 28 +++++ ...oreFrontMyAccountWithMultishipmentTest.xml | 4 +- .../StorefrontOrderWithMultishippingTest.xml | 105 ++++++++++++++++++ ...rontCustomerOrdersViewOrderActionGroup.xml | 22 ++++ .../StorefrontCustomerOrdersGridSection.xml | 4 +- 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml create mode 100644 app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml diff --git a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml b/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml new file mode 100644 index 0000000000000..9281cdf03a1ab --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + sumTotalValue + grandTotalValue + + + diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml index ad68b709c5729..d8b6a35a4885c 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontMyAccountWithMultishipmentTest.xml @@ -12,13 +12,13 @@ - + <title value="DEPRECATED. Verify Shipping price for Storefront after multiple address checkout"/> <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> <severity value="CRITICAL"/> <testCaseId value="MC-19303"/> <group value="multishipping"/> <skip> - <issueId value="MC-22683"/> + <issueId value="DEPRECATED">Please use StorefrontOrderWithMultishippingTest instead</issueId> </skip> </annotations> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml new file mode 100644 index 0000000000000..26a1892cb679e --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -0,0 +1,105 @@ +<?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="StorefrontOrderWithMultishippingTest"> + <annotations> + <features value="Multishipping"/> + <stories value="Shipping price shows 0 on Order view page after multiple address checkout"/> + <title value="Verify Shipping price for Storefront after multiple address checkout"/> + <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-28900"/> + <group value="catalog"/> + <group value="sales"/> + <group value="multishipping"/> + </annotations> + + <before> + <createData entity="SimpleProduct2" stepKey="createProduct1"/> + <createData entity="SimpleProduct2" stepKey="createProduct2"/> + <createData entity="Simple_US_Customer_Two_Addresses" stepKey="createCustomer"/> + <!-- Set configurations --> + <magentoCLI command="config:set {{EnableMultiShippingCheckoutMultiple.path}} {{EnableMultiShippingCheckoutMultiple.value}}" stepKey="allowShippingToMultipleAddresses"/> + <magentoCLI command="config:set {{EnableFreeShippingMethod.path}} {{EnableFreeShippingMethod.value}}" stepKey="enableFreeShipping"/> + <magentoCLI command="config:set {{EnableFlatRateShippingMethod.path}} {{EnableFlatRateShippingMethod.value}}" stepKey="enableFlatRateShipping"/> + <magentoCLI command="config:set {{EnableCheckMoneyOrderPaymentMethod.path}} {{EnableCheckMoneyOrderPaymentMethod.value}}" stepKey="enableCheckMoneyOrderPaymentMethod"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + </before> + + <after> + <deleteData createDataKey="createProduct1" stepKey="deleteProduct1"/> + <deleteData createDataKey="createProduct2" stepKey="deleteProduct2"/> + <!-- Need logout before customer delete. Fatal error appears otherwise --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <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"/> + </after> + + <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct1ToCart"> + <argument name="product" value="$$createProduct1$$"/> + </actionGroup> + <actionGroup ref="AddSimpleProductToCartActionGroup" stepKey="addSimpleProduct2ToCart"> + <argument name="product" value="$$createProduct2$$"/> + </actionGroup> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> + <actionGroup ref="CheckingWithMultipleAddressesActionGroup" stepKey="checkoutWithMultipleAddresses"/> + <waitForPageLoad stepKey="waitForShippingInfoPageLoad"/> + <actionGroup ref="SelectMultiShippingInfoActionGroup" stepKey="checkoutWithMultipleShipping"/> + <!--Select Check / Money order Payment method--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> + <actionGroup ref="SelectBillingInfoActionGroup" stepKey="checkoutWithPaymentMethod"/> + <waitForPageLoad stepKey="waitForReviewOrderPageLoad"/> + <actionGroup ref="ReviewOrderForMultiShipmentActionGroup" stepKey="reviewOrderForMultiShipment"> + <argument name="totalNameForFirstOrder" value="Shipping & Handling"/> + <argument name="totalPositionForFirstOrder" value="1"/> + <argument name="totalNameForSecondOrder" value="Shipping & Handling"/> + <argument name="totalPositionForSecondOrder" value="2"/> + </actionGroup> + <waitForPageLoad stepKey="waitForPlaceOrderPageLoad"/> + <actionGroup ref="StorefrontPlaceOrderForMultipleAddressesActionGroup" stepKey="placeOrder"> + <argument name="firstOrderPosition" value="1"/> + <argument name="secondOrderPosition" value="2"/> + </actionGroup> + <waitForPageLoad stepKey="waitForOrderPageLoad"/> + + <!-- Check first order--> + <actionGroup ref="StorefrontCustomerOrdersViewOrderActionGroup" stepKey="openFirstOrder"> + <argument name="orderNumber" value="{$getFirstOrderIdPlaceOrder}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup" stepKey="checkFirstOrderTotals"/> + <!-- Check second order--> + <actionGroup ref="StorefrontCustomerOrdersViewOrderActionGroup" stepKey="openSecondOrder"> + <argument name="orderNumber" value="{$getSecondOrderIdPlaceOrder}"/> + </actionGroup> + <actionGroup ref="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup" stepKey="checkSecondOrderTotals"/> + + <!--Assert order in orders grid --> + <!-- Go to order page --> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openFirstOrderPage"> + <argument name="orderId" value="{$getFirstOrderIdPlaceOrder}"/> + </actionGroup> + <!-- Check status --> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeFirstOrderPendingStatus"/> + <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForFirstOrder"/> + <!-- Go to order page --> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openSecondOrderPage"> + <argument name="orderId" value="{$getSecondOrderIdPlaceOrder}"/> + </actionGroup> + <!-- Check status --> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeSecondOrderPendingStatus"/> + <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForSecondOrder"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.xml new file mode 100644 index 0000000000000..88d79268d440e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontCustomerOrdersViewOrderActionGroup.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="StorefrontCustomerOrdersViewOrderActionGroup"> + <annotations> + <description>Navigate to customer dashboard -> orders. Press 'View Order' button for specified order number. Notice: customer should be logged in.</description> + </annotations> + <arguments> + <argument name="orderNumber" type="string" defaultValue="000000001"/> + </arguments> + + <amOnPage url="{{StorefrontCustomerOrdersHistoryPage.url}}" stepKey="openCustomerOrdersHistoryPage"/> + <click selector="{{StorefrontCustomerOrdersGridSection.orderView(orderNumber)}}" stepKey="clickViewOrderButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml index c0deb9ab55d2b..5b079891f657a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.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="StorefrontCustomerOrdersGridSection"> - <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" /> - <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" /> + <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> + <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> </section> </sections> From 89d09ac6bcfdcf5a22f86ff83999893627eca081 Mon Sep 17 00:00:00 2001 From: Tejash Kumbhare <tejas@wagento.com> Date: Mon, 13 Jan 2020 10:27:05 +0530 Subject: [PATCH 149/666] revert back and added comma --- .../AdminAnalytics/view/adminhtml/templates/notification.phtml | 2 +- .../Test/Unit/Model/Product/Plugin/UpdateQuoteItemsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml index 81b923be71655..4b1f971670184 100644 --- a/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml +++ b/app/code/Magento/AdminAnalytics/view/adminhtml/templates/notification.phtml @@ -10,7 +10,7 @@ define('analyticsPopupConfig', function () { return { analyticsVisible: <?= $block->getNotification()->isAnalyticsVisible() ? 1 : 0; ?>, - releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?> + releaseVisible: <?= $block->getNotification()->isReleaseVisible() ? 1 : 0; ?>, } }); </script> 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 896879c4f67c6..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 @@ -58,7 +58,7 @@ public function aroundUpdateDataProvider() [10, 20, 'once'], [null, 10, 'never'], [10, 10, 'never'], - [10, 10, 'once', true] + [10, 10, 'once', true], ]; } } From b94c4abbbdd9780936ac399a3c1e054800c4c43b Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 13 Jan 2020 11:36:21 +0200 Subject: [PATCH 150/666] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/SearchEntityResultsTest.xml | 4 +- ...ontQuickSearchConfigurableChildrenTest.xml | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index cc6f202272e3b..c289fc7868a10 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -607,14 +607,14 @@ <test name="QuickSearchConfigurableChildren"> <annotations> <stories value="Search Product on Storefront"/> - <title value="User should be able to use Quick Search to a configurable product's child products"/> + <title value="Deprecated. User should be able to use Quick Search to a configurable product's child products"/> <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> <testCaseId value="MC-14798"/> <group value="CatalogSearch"/> <group value="mtf_migrated"/> <skip> - <issueId value="MC-15101"/> + <issueId value="DEPRECATED">Use StorefrontQuickSearchConfigurableChildrenTest instead.</issueId> </skip> </annotations> <before> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml new file mode 100644 index 0000000000000..03ce878ef4f9f --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -0,0 +1,109 @@ +<?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="StorefrontQuickSearchConfigurableChildrenTest"> + <annotations> + <stories value="Search Product on Storefront"/> + <title value="User should be able to use Quick Search to a configurable product's child products"/> + <description value="Use Quick Search to find a configurable product with enabled/disable children"/> + <severity value="MAJOR"/> + <testCaseId value="MC-14798"/> + <group value="CatalogSearch"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create the category --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <!-- Create blank AttributeSet--> + <createData entity="CatalogAttributeSet" stepKey="createAttributeSet"/> + <!-- Create an attribute with two options to be used in the first child product --> + <createData entity="hiddenDropdownAttributeWithOptions" stepKey="createProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createProductAttributeOption"> + <requiredEntity createDataKey="createProductAttribute"/> + </createData> + + <!-- Assign attribute to set --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="GoToAttributeGridPageActionGroup" stepKey="goToAttributeSetPage"/> + <actionGroup ref="GoToAttributeSetByNameActionGroup" stepKey="openAttributeSetByName"> + <argument name="name" value="$createAttributeSet.attribute_set_name$"/> + </actionGroup> + <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignAttributeToGroup"> + <argument name="group" value="Product Details"/> + <argument name="attribute" value="$createProductAttribute.attribute_code$"/> + </actionGroup> + <actionGroup ref="SaveAttributeSetActionGroup" stepKey="savePage"/> + + <!-- Get the first option of the attribute we created --> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getAttributeOption"> + <requiredEntity createDataKey="createProductAttribute"/> + </getData> + + <!-- Create a simple product --> + <createData entity="ApiSimpleOneHidden" storeCode="all" stepKey="createSimpleProduct"> + <field key="attribute_set_id">$createAttributeSet.attribute_set_id$</field> + <requiredEntity createDataKey="createProductAttribute"/> + <requiredEntity createDataKey="getAttributeOption"/> + </createData> + <updateData entity="ApiSimpleProductUpdateDescription" createDataKey="createSimpleProduct" stepKey="updateSimpleProduct"/> + + <!-- Create the configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigurableProduct"> + <field key="attribute_set_id">$createAttributeSet.attribute_set_id$</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- Create the configurable product option --> + <createData entity="ConfigurableProductOneOption" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createProductAttribute"/> + <requiredEntity createDataKey="getAttributeOption"/> + </createData> + <!-- Add the first simple product to the configurable product --> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + + <!-- Perform reindex --> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigurableProduct"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> + <argument name="phrase" value="$createConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> + <argument name="productName" value="$createConfigurableProduct.name$"/> + <argument name="index" value="1"/> + </actionGroup> + + <!-- Disable Child Product --> + <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="openSimpleProduct"> + <argument name="productId" value="$createSimpleProduct.id$"/> + </actionGroup> + <actionGroup ref="ToggleProductEnabledActionGroup" stepKey="disableProduct"/> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePageAgain"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefrontAgain"> + <argument name="phrase" value="$createConfigurableProduct.name$"/> + </actionGroup> + <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGridActionGroup" stepKey="dontSeeProductAnymore"> + <argument name="productName" value="$createConfigurableProduct.name$"/> + </actionGroup> + </test> +</tests> From 0228d4bf27c243d10b0dfcef56cca5bd13579f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sun, 12 Jan 2020 02:16:07 +0100 Subject: [PATCH 151/666] Refactor + `array_merge` in loop replace + PHPCS fixes --- .../CatalogInventory/Model/StockIndex.php | 45 +++++---- .../Model/Search/FiltersExtractor.php | 37 ++++---- .../Model/Category/Plugin/Store/Group.php | 46 ++++----- .../Block/Product/ProductsList.php | 78 +++++++++------- .../Model/AgreementsValidator.php | 16 ++-- .../Model/System/Currencysymbol.php | 15 +-- .../Observer/CurrencyDisplayOptionsTest.php | 11 ++- .../Model/Address/CompositeValidator.php | 6 +- .../Magento/Customer/Model/Metadata/Form.php | 8 +- .../Attribute/Source/CountryWithWebsites.php | 48 ++++++---- .../Model/Import/Address.php | 18 ++-- .../Model/Import/Customer.php | 16 ++-- app/code/Magento/Deploy/Package/Package.php | 9 +- .../Package/Processor/PreProcessor/Css.php | 13 ++- .../Command/XmlCatalogGenerateCommand.php | 56 ++++++----- .../Directory/Model/AllowedCountries.php | 8 +- .../Attribute/Edit/Options/Options.php | 11 +-- app/code/Magento/Eav/Model/Form.php | 12 ++- .../Product/CompositeFieldProvider.php | 6 +- .../Block/Cart/Item/Renderer/Grouped.php | 6 +- .../Block/Stockqty/Type/Grouped.php | 6 +- .../ProcessingErrorAggregator.php | 16 ++-- .../Activate/Permissions/Tab/Webapi.php | 16 ++-- .../PageCache/Model/Layout/LayoutPlugin.php | 6 +- .../Gateway/Validator/ValidatorComposite.php | 22 ++--- .../Structure/PaymentSectionModifier.php | 24 +++-- .../Cart/BuyRequest/BuyRequestBuilder.php | 6 +- .../Magento/Reports/Block/Product/Viewed.php | 9 +- .../Adminhtml/Items/Column/DefaultColumn.php | 10 +- .../Block/Order/Email/Items/DefaultItems.php | 18 ++-- .../Order/Email/Items/Order/DefaultOrder.php | 30 +++--- .../Order/Item/Renderer/DefaultRenderer.php | 39 ++++---- .../Model/Order/Pdf/Items/AbstractItems.php | 83 ++++++++++------- .../Provider/NotSyncedDataProvider.php | 13 ++- .../Magento/Search/Model/Autocomplete.php | 11 ++- .../Search/Model/SynonymGroupRepository.php | 17 ++-- .../Calculation/Rate/Collection.php | 65 +++++++------ .../Magento/Weee/Model/Total/Quote/Weee.php | 93 ++++++++++--------- 38 files changed, 523 insertions(+), 426 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/StockIndex.php b/app/code/Magento/CatalogInventory/Model/StockIndex.php index 41db057cf149c..af211b98386bd 100644 --- a/app/code/Magento/CatalogInventory/Model/StockIndex.php +++ b/app/code/Magento/CatalogInventory/Model/StockIndex.php @@ -10,12 +10,15 @@ use Magento\Catalog\Model\Product\Website as ProductWebsite; use Magento\Catalog\Model\ProductFactory; use Magento\CatalogInventory\Api\StockIndexInterface; +use Magento\CatalogInventory\Model\ResourceModel\Stock\Status as StockStatusResourceModel; use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Framework\App\ObjectManager; /** - * Class StockIndex + * Index responsible for Stock + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class StockIndex implements StockIndexInterface @@ -31,7 +34,7 @@ class StockIndex implements StockIndexInterface protected $productRepository; /** - * @var \Magento\CatalogInventory\Model\ResourceModel\Stock\Status + * @var StockStatusResourceModel */ protected $stockStatusResource; @@ -47,6 +50,11 @@ class StockIndex implements StockIndexInterface */ protected $websites; + /** + * @var ProductWebsite + */ + private $productWebsite; + /** * Product Type Instances cache * @@ -88,7 +96,7 @@ public function rebuild($productId = null, $scopeId = null) } else { $lastProductId = 0; while (true) { - /** @var \Magento\CatalogInventory\Model\ResourceModel\Stock\Status $resource */ + /** @var StockStatusResourceModel $resource */ $resource = $this->getStockStatusResource(); $productCollection = $resource->getProductCollection($lastProductId); if (!$productCollection) { @@ -132,7 +140,7 @@ public function updateProductStockStatus($productId, $websiteId) * @param int $websiteId * @param int $qty * @param int $status - * @return $this + * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function processChildren( @@ -160,10 +168,12 @@ protected function processChildren( $requiredChildrenIds = $typeInstance->getChildrenIds($productId, true); if ($requiredChildrenIds) { - $childrenIds = []; + $childrenIds = [[]]; foreach ($requiredChildrenIds as $groupedChildrenIds) { - $childrenIds = array_merge($childrenIds, $groupedChildrenIds); + $childrenIds[] = $groupedChildrenIds; } + $childrenIds = array_merge(...$childrenIds); + $childrenWebsites = $this->productWebsite->getWebsites($childrenIds); foreach ($websitesWithStores as $websiteId => $storeId) { $childrenStatus = $this->getStockStatusResource()->getProductStatus($childrenIds, $storeId); @@ -201,7 +211,7 @@ protected function processChildren( protected function getWebsitesWithDefaultStores($websiteId = null) { if ($this->websites === null) { - /** @var \Magento\CatalogInventory\Model\ResourceModel\Stock\Status $resource */ + /** @var StockStatusResourceModel $resource */ $resource = $this->getStockStatusResource(); $this->websites = $resource->getWebsiteStores(); } @@ -217,17 +227,19 @@ protected function getWebsitesWithDefaultStores($websiteId = null) * * @param int $productId * @param int $websiteId - * @return $this + * @return void */ protected function processParents($productId, $websiteId) { - $parentIds = []; + $parentIds = [[]]; foreach ($this->getProductTypeInstances() as $typeInstance) { /* @var $typeInstance AbstractType */ - $parentIds = array_merge($parentIds, $typeInstance->getParentIdsByChild($productId)); + $parentIds[] = $typeInstance->getParentIdsByChild($productId); } - if (!$parentIds) { + $parentIds = array_merge(...$parentIds); + + if (empty($parentIds)) { return $this; } @@ -244,8 +256,7 @@ protected function processParents($productId, $websiteId) } /** - * Retrieve Product Type Instances - * as key - type code, value - instance model + * Retrieve Product Type Instances as key - type code, value - instance model * * @return array */ @@ -262,14 +273,14 @@ protected function getProductTypeInstances() } /** - * @return \Magento\CatalogInventory\Model\ResourceModel\Stock\Status + * Returns ResourceModel for Stock Status + * + * @return StockStatusResourceModel */ protected function getStockStatusResource() { if (empty($this->stockStatusResource)) { - $this->stockStatusResource = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\CatalogInventory\Model\ResourceModel\Stock\Status::class - ); + $this->stockStatusResource = ObjectManager::getInstance()->get(StockStatusResourceModel::class); } return $this->stockStatusResource; } diff --git a/app/code/Magento/CatalogSearch/Model/Search/FiltersExtractor.php b/app/code/Magento/CatalogSearch/Model/Search/FiltersExtractor.php index 55c8582979912..63d7ee0e6e4c0 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/FiltersExtractor.php +++ b/app/code/Magento/CatalogSearch/Model/Search/FiltersExtractor.php @@ -10,11 +10,10 @@ use Magento\Framework\Search\Request\Filter\BoolExpression; /** - * Class FiltersExtractor * Extracts filters from QueryInterface * - * @deprecated - * @see \Magento\ElasticSearch + * @deprecated Use Magento\Elasticsearch implementation of QueryInterface + * @see \Magento\Elasticsearch */ class FiltersExtractor { @@ -26,19 +25,19 @@ class FiltersExtractor */ public function extractFiltersFromQuery(QueryInterface $query) { - $filters = []; + $filters = [[]]; switch ($query->getType()) { case QueryInterface::TYPE_BOOL: /** @var \Magento\Framework\Search\Request\Query\BoolExpression $query */ foreach ($query->getMust() as $subQuery) { - $filters = array_merge($filters, $this->extractFiltersFromQuery($subQuery)); + $filters[] = $this->extractFiltersFromQuery($subQuery); } foreach ($query->getShould() as $subQuery) { - $filters = array_merge($filters, $this->extractFiltersFromQuery($subQuery)); + $filters[] = $this->extractFiltersFromQuery($subQuery); } foreach ($query->getMustNot() as $subQuery) { - $filters = array_merge($filters, $this->extractFiltersFromQuery($subQuery)); + $filters[] = $this->extractFiltersFromQuery($subQuery); } break; @@ -46,9 +45,9 @@ public function extractFiltersFromQuery(QueryInterface $query) /** @var Filter $query */ $filter = $query->getReference(); if (FilterInterface::TYPE_BOOL === $filter->getType()) { - $filters = array_merge($filters, $this->getFiltersFromBoolFilter($filter)); + $filters[] = $this->getFiltersFromBoolFilter($filter); } else { - $filters[] = $filter; + $filters[] = [$filter]; } break; @@ -56,39 +55,41 @@ public function extractFiltersFromQuery(QueryInterface $query) break; } - return $filters; + return array_merge(...$filters); } /** + * Returns list of filters from Bool filter + * * @param BoolExpression $boolExpression * @return FilterInterface[] */ private function getFiltersFromBoolFilter(BoolExpression $boolExpression) { - $filters = []; + $filters = [[]]; /** @var BoolExpression $filter */ foreach ($boolExpression->getMust() as $filter) { if ($filter->getType() === FilterInterface::TYPE_BOOL) { - $filters = array_merge($filters, $this->getFiltersFromBoolFilter($filter)); + $filters[] = $this->getFiltersFromBoolFilter($filter); } else { - $filters[] = $filter; + $filters[] = [$filter]; } } foreach ($boolExpression->getShould() as $filter) { if ($filter->getType() === FilterInterface::TYPE_BOOL) { - $filters = array_merge($filters, $this->getFiltersFromBoolFilter($filter)); + $filters[] = $this->getFiltersFromBoolFilter($filter); } else { - $filters[] = $filter; + $filters[] = [$filter]; } } foreach ($boolExpression->getMustNot() as $filter) { if ($filter->getType() === FilterInterface::TYPE_BOOL) { - $filters = array_merge($filters, $this->getFiltersFromBoolFilter($filter)); + $filters[] = $this->getFiltersFromBoolFilter($filter); } else { - $filters[] = $filter; + $filters[] = [$filter]; } } - return $filters; + return array_merge(...$filters); } } 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 1dbfad6cf5219..308b82e38c43a 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/Group.php @@ -5,6 +5,7 @@ */ namespace Magento\CatalogUrlRewrite\Model\Category\Plugin\Store; +use Magento\Store\Model\ResourceModel\Group as StoreGroup; use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; use Magento\Catalog\Model\CategoryFactory; @@ -16,37 +17,39 @@ use Magento\Framework\Model\AbstractModel; /** + * Generate Product and Category URLs + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Group { /** - * @var \Magento\UrlRewrite\Model\UrlPersistInterface + * @var UrlPersistInterface */ protected $urlPersist; /** - * @var \Magento\Catalog\Model\CategoryFactory + * @var CategoryFactory */ protected $categoryFactory; /** - * @var \Magento\Catalog\Model\ProductFactory + * @var ProductFactory */ protected $productFactory; /** - * @var \Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator + * @var CategoryUrlRewriteGenerator */ protected $categoryUrlRewriteGenerator; /** - * @var \Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator + * @var ProductUrlRewriteGenerator */ protected $productUrlRewriteGenerator; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $storeManager; @@ -77,15 +80,15 @@ public function __construct( /** * Perform updating url for categories and products assigned to the group * - * @param \Magento\Store\Model\ResourceModel\Group $subject - * @param \Magento\Store\Model\ResourceModel\Group $result + * @param StoreGroup $subject + * @param StoreGroup $result * @param AbstractModel $group - * @return \Magento\Store\Model\ResourceModel\Group + * @return StoreGroup * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterSave( - \Magento\Store\Model\ResourceModel\Group $subject, - \Magento\Store\Model\ResourceModel\Group $result, + StoreGroup $subject, + StoreGroup $result, AbstractModel $group ) { if (!$group->isObjectNew() @@ -118,7 +121,7 @@ public function afterSave( */ protected function generateProductUrls($websiteId, $originWebsiteId) { - $urls = []; + $urls = [[]]; $websiteIds = $websiteId != $originWebsiteId ? [$websiteId, $originWebsiteId] : [$websiteId]; @@ -130,33 +133,30 @@ protected function generateProductUrls($websiteId, $originWebsiteId) foreach ($collection as $product) { /** @var \Magento\Catalog\Model\Product $product */ $product->setStoreId(Store::DEFAULT_STORE_ID); - $urls = array_merge( - $urls, - $this->productUrlRewriteGenerator->generate($product) - ); + $urls[] = $this->productUrlRewriteGenerator->generate($product); } - return $urls; + return array_merge(...$urls); } /** + * Generate url rewrites for categories assigned to store + * * @param int $rootCategoryId * @param array $storeIds * @return array */ protected function generateCategoryUrls($rootCategoryId, $storeIds) { - $urls = []; + $urls = [[]]; $categories = $this->categoryFactory->create()->getCategories($rootCategoryId, 1, false, true); foreach ($categories as $category) { /** @var \Magento\Catalog\Model\Category $category */ $category->setStoreId(Store::DEFAULT_STORE_ID); $category->setStoreIds($storeIds); - $urls = array_merge( - $urls, - $this->categoryUrlRewriteGenerator->generate($category) - ); + $urls[] = $this->categoryUrlRewriteGenerator->generate($category); } - return $urls; + + return array_merge(...$urls); } } diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php index 9e47830debfc4..22e3a7382cdac 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php +++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php @@ -6,15 +6,26 @@ namespace Magento\CatalogWidget\Block\Product; +use Magento\Catalog\Block\Product\AbstractProduct; +use Magento\Catalog\Block\Product\Context; +use Magento\Catalog\Block\Product\Widget\Html\Pager as ProductBlockPager; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Visibility as ProductVisibility; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory; +use Magento\CatalogWidget\Model\Rule; +use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\App\ObjectManager; use Magento\Framework\App\ActionInterface; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\Url\EncoderInterface as UrlEncoderInterface; +use Magento\Framework\View\Element\RendererList; use Magento\Framework\View\LayoutFactory; +use Magento\Rule\Model\Condition\Sql\Builder as SqlConditionBuilder; use Magento\Widget\Block\BlockInterface; use Magento\Framework\Url\EncoderInterface; +use Magento\Widget\Helper\Conditions as ConditionsHelper; /** * Catalog Products List widget block @@ -22,7 +33,7 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ -class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implements BlockInterface, IdentityInterface +class ProductsList extends AbstractProduct implements BlockInterface, IdentityInterface { /** * Default value for products count that will be shown @@ -32,7 +43,8 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem /** * Name of request parameter for page number value * - * @deprecated + * @deprecated No longer used for Magento Core + * @see self::getData('page_var_name') */ const PAGE_VAR_NAME = 'np'; @@ -49,41 +61,41 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem /** * Instance of pager block * - * @var \Magento\Catalog\Block\Product\Widget\Html\Pager + * @var ProductBlockPager */ protected $pager; /** - * @var \Magento\Framework\App\Http\Context + * @var HttpContext */ protected $httpContext; /** * Catalog product visibility * - * @var \Magento\Catalog\Model\Product\Visibility + * @var ProductVisibility */ protected $catalogProductVisibility; /** * Product collection factory * - * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory + * @var ProductCollectionFactory */ protected $productCollectionFactory; /** - * @var \Magento\Rule\Model\Condition\Sql\Builder + * @var SqlConditionBuilder */ protected $sqlBuilder; /** - * @var \Magento\CatalogWidget\Model\Rule + * @var Rule */ protected $rule; /** - * @var \Magento\Widget\Helper\Conditions + * @var ConditionsHelper */ protected $conditionsHelper; @@ -105,38 +117,38 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem private $layoutFactory; /** - * @var \Magento\Framework\Url\EncoderInterface|null + * @var UrlEncoderInterface|null */ private $urlEncoder; /** - * @var \Magento\Framework\View\Element\RendererList + * @var RendererList */ private $rendererListBlock; /** - * @param \Magento\Catalog\Block\Product\Context $context - * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory - * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Rule\Model\Condition\Sql\Builder $sqlBuilder - * @param \Magento\CatalogWidget\Model\Rule $rule - * @param \Magento\Widget\Helper\Conditions $conditionsHelper + * @param Context $context + * @param ProductCollectionFactory $productCollectionFactory + * @param ProductVisibility $catalogProductVisibility + * @param HttpContext $httpContext + * @param SqlConditionBuilder $sqlBuilder + * @param Rule $rule + * @param ConditionsHelper $conditionsHelper * @param array $data * @param Json|null $json * @param LayoutFactory|null $layoutFactory - * @param \Magento\Framework\Url\EncoderInterface|null $urlEncoder + * @param UrlEncoderInterface|null $urlEncoder * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Catalog\Block\Product\Context $context, - \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory, - \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Rule\Model\Condition\Sql\Builder $sqlBuilder, - \Magento\CatalogWidget\Model\Rule $rule, - \Magento\Widget\Helper\Conditions $conditionsHelper, + Context $context, + ProductCollectionFactory $productCollectionFactory, + ProductVisibility $catalogProductVisibility, + HttpContext $httpContext, + SqlConditionBuilder $sqlBuilder, + Rule $rule, + ConditionsHelper $conditionsHelper, array $data = [], Json $json = null, LayoutFactory $layoutFactory = null, @@ -173,7 +185,8 @@ protected function _construct() $this->addData([ 'cache_lifetime' => 86400, - 'cache_tags' => [\Magento\Catalog\Model\Product::CACHE_TAG, + 'cache_tags' => [ + Product::CACHE_TAG, ], ]); } @@ -210,7 +223,7 @@ public function getCacheKeyInfo() * @SuppressWarnings(PHPMD.NPathComplexity) */ public function getProductPriceHtml( - \Magento\Catalog\Model\Product $product, + Product $product, $priceType = null, $renderZone = \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, array $arguments = [] @@ -418,7 +431,7 @@ public function getPagerHtml() if ($this->showPager() && $this->getProductCollection()->getSize() > $this->getProductsPerPage()) { if (!$this->pager) { $this->pager = $this->getLayout()->createBlock( - \Magento\Catalog\Block\Product\Widget\Html\Pager::class, + ProductBlockPager::class, $this->getWidgetPagerBlockName() ); @@ -444,16 +457,17 @@ public function getPagerHtml() */ public function getIdentities() { - $identities = []; + $identities = [[]]; if ($this->getProductCollection()) { foreach ($this->getProductCollection() as $product) { if ($product instanceof IdentityInterface) { - $identities = array_merge($identities, $product->getIdentities()); + $identities[] = $product->getIdentities(); } } } + $identities = array_merge(...$identities); - return $identities ?: [\Magento\Catalog\Model\Product::CACHE_TAG]; + return $identities ?: [Product::CACHE_TAG]; } /** diff --git a/app/code/Magento/CheckoutAgreements/Model/AgreementsValidator.php b/app/code/Magento/CheckoutAgreements/Model/AgreementsValidator.php index 8d25ba88c0f82..2643e69ba1efd 100644 --- a/app/code/Magento/CheckoutAgreements/Model/AgreementsValidator.php +++ b/app/code/Magento/CheckoutAgreements/Model/AgreementsValidator.php @@ -5,13 +5,15 @@ */ namespace Magento\CheckoutAgreements\Model; +use Magento\Checkout\Api\AgreementsValidatorInterface; + /** - * Class AgreementsValidator + * Validator for Checkout Agreements */ -class AgreementsValidator implements \Magento\Checkout\Api\AgreementsValidatorInterface +class AgreementsValidator implements AgreementsValidatorInterface { /** - * @var \Magento\CheckoutAgreements\Model\AgreementsProviderInterface[] + * @var AgreementsProviderInterface[] */ protected $agreementsProviders; @@ -33,11 +35,13 @@ public function __construct($list = null) public function isValid($agreementIds = []) { $agreementIds = $agreementIds === null ? [] : $agreementIds; - $requiredAgreements = []; + $requiredAgreements = [[]]; foreach ($this->agreementsProviders as $agreementsProvider) { - $requiredAgreements = array_merge($requiredAgreements, $agreementsProvider->getRequiredAgreementIds()); + $requiredAgreements[] = $agreementsProvider->getRequiredAgreementIds(); } - $agreementsDiff = array_diff($requiredAgreements, $agreementIds); + + $agreementsDiff = array_diff(array_merge(...$requiredAgreements), $agreementIds); + return empty($agreementsDiff); } } diff --git a/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php b/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php index 6c7019986cce0..d48df02d9de27 100644 --- a/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php +++ b/app/code/Magento/CurrencySymbol/Model/System/Currencysymbol.php @@ -292,7 +292,8 @@ protected function _unserializeStoreConfig($configPath, $storeId = null) */ protected function getAllowedCurrencies() { - $allowedCurrencies = explode( + $allowedCurrencies = [[]]; + $allowedCurrencies[] = explode( self::ALLOWED_CURRENCIES_CONFIG_SEPARATOR, $this->_scopeConfig->getValue( self::XML_PATH_ALLOWED_CURRENCIES, @@ -318,23 +319,17 @@ protected function getAllowedCurrencies() if (!$websiteShow) { $websiteShow = true; $websiteSymbols = $website->getConfig(self::XML_PATH_ALLOWED_CURRENCIES); - $allowedCurrencies = array_merge( - $allowedCurrencies, - explode(self::ALLOWED_CURRENCIES_CONFIG_SEPARATOR, $websiteSymbols) - ); + $allowedCurrencies[] = explode(self::ALLOWED_CURRENCIES_CONFIG_SEPARATOR, $websiteSymbols); } $storeSymbols = $this->_scopeConfig->getValue( self::XML_PATH_ALLOWED_CURRENCIES, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store ); - $allowedCurrencies = array_merge( - $allowedCurrencies, - explode(self::ALLOWED_CURRENCIES_CONFIG_SEPARATOR, $storeSymbols) - ); + $allowedCurrencies[] = explode(self::ALLOWED_CURRENCIES_CONFIG_SEPARATOR, $storeSymbols); } } } - return array_unique($allowedCurrencies); + return array_unique(array_merge(...$allowedCurrencies)); } } diff --git a/app/code/Magento/CurrencySymbol/Test/Unit/Observer/CurrencyDisplayOptionsTest.php b/app/code/Magento/CurrencySymbol/Test/Unit/Observer/CurrencyDisplayOptionsTest.php index dd0d7ffc8cc68..ae8c12c2019b8 100644 --- a/app/code/Magento/CurrencySymbol/Test/Unit/Observer/CurrencyDisplayOptionsTest.php +++ b/app/code/Magento/CurrencySymbol/Test/Unit/Observer/CurrencyDisplayOptionsTest.php @@ -6,6 +6,7 @@ namespace Magento\CurrencySymbol\Test\Unit\Observer; use Magento\CurrencySymbol\Model\System\CurrencysymbolFactory; +use Magento\Framework\Locale\Currency; /** * Test for \Magento\CurrencySymbol\Observer\CurrencyDisplayOptions @@ -65,7 +66,7 @@ protected function setUp() public function testCurrencyDisplayOptionsEmpty() { $baseData = [ - \Magento\Framework\Locale\Currency::CURRENCY_OPTION_NAME => 'US Dollar' + Currency::CURRENCY_OPTION_NAME => 'US Dollar' ]; $sampleCurrencyOptionObject = new \Magento\Framework\DataObject($baseData); @@ -83,7 +84,7 @@ public function testCurrencyDisplayOptionsEmpty() public function testCurrencyDisplayOptions() { $baseData = [ - \Magento\Framework\Locale\Currency::CURRENCY_OPTION_NAME => 'US Dollar' + Currency::CURRENCY_OPTION_NAME => 'US Dollar' ]; $sampleCurrencyOptionObject = new \Magento\Framework\DataObject($baseData); $sampleCurrency = 'USD'; @@ -92,9 +93,9 @@ public function testCurrencyDisplayOptions() $expectedCurrencyOptions = array_merge( $baseData, [ - \Magento\Framework\Locale\Currency::CURRENCY_OPTION_NAME => 'US Dollar', - \Magento\Framework\Locale\Currency::CURRENCY_OPTION_SYMBOL => $sampleCurrencySymbol, - \Magento\Framework\Locale\Currency::CURRENCY_OPTION_DISPLAY => \Magento\Framework\Currency::USE_SYMBOL + Currency::CURRENCY_OPTION_NAME => 'US Dollar', + Currency::CURRENCY_OPTION_SYMBOL => $sampleCurrencySymbol, + Currency::CURRENCY_OPTION_DISPLAY => \Magento\Framework\Currency::USE_SYMBOL ] ); diff --git a/app/code/Magento/Customer/Model/Address/CompositeValidator.php b/app/code/Magento/Customer/Model/Address/CompositeValidator.php index 1d16a929532f5..4c77f10c11de4 100644 --- a/app/code/Magento/Customer/Model/Address/CompositeValidator.php +++ b/app/code/Magento/Customer/Model/Address/CompositeValidator.php @@ -30,11 +30,11 @@ public function __construct( */ public function validate(AbstractAddress $address) { - $errors = []; + $errors = [[]]; foreach ($this->validators as $validator) { - $errors = array_merge($errors, $validator->validate($address)); + $errors[] = $validator->validate($address); } - return $errors; + return array_merge(...$errors); } } diff --git a/app/code/Magento/Customer/Model/Metadata/Form.php b/app/code/Magento/Customer/Model/Metadata/Form.php index 6df969f625376..85637ebf508b8 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form.php +++ b/app/code/Magento/Customer/Model/Metadata/Form.php @@ -9,6 +9,8 @@ use Magento\Customer\Api\CustomerMetadataInterface; /** + * Customer Form metadata model + * * @api * @since 100.0.2 */ @@ -361,11 +363,11 @@ public function validateData(array $data) { $validator = $this->_getValidator($data); if (!$validator->isValid(false)) { - $messages = []; + $messages = [[]]; foreach ($validator->getMessages() as $errorMessages) { - $messages = array_merge($messages, (array)$errorMessages); + $messages[] = (array)$errorMessages; } - return $messages; + return array_merge(...$messages); } return true; } diff --git a/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php index ce6278b446302..020067570efb4 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php +++ b/app/code/Magento/Customer/Model/ResourceModel/Address/Attribute/Source/CountryWithWebsites.php @@ -12,18 +12,28 @@ namespace Magento\Customer\Model\ResourceModel\Address\Attribute\Source; use Magento\Customer\Model\Config\Share; +use Magento\Customer\Model\Config\Share as CustomerShareConfig; use Magento\Directory\Model\AllowedCountries; +use Magento\Directory\Model\ResourceModel\Country\Collection as CountryCollection; +use Magento\Directory\Model\ResourceModel\Country\CollectionFactory as CountryCollectionFactory; +use Magento\Eav\Model\Entity\Attribute\Source\Table; +use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory as OptionCollectionFactory; +use Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory as AttrubuteOptionFactory; use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; -class CountryWithWebsites extends \Magento\Eav\Model\Entity\Attribute\Source\Table +/** + * Return allowed countries for specified website + */ +class CountryWithWebsites extends Table { /** - * @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory + * @var CountryCollectionFactory */ private $countriesFactory; /** - * @var \Magento\Directory\Model\AllowedCountries + * @var AllowedCountries */ private $allowedCountriesReader; @@ -33,7 +43,7 @@ class CountryWithWebsites extends \Magento\Eav\Model\Entity\Attribute\Source\Tab private $options; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ private $storeManager; @@ -43,21 +53,20 @@ class CountryWithWebsites extends \Magento\Eav\Model\Entity\Attribute\Source\Tab private $shareConfig; /** - * CountryWithWebsites constructor. - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory + * @param OptionCollectionFactory $attrOptionCollectionFactory + * @param AttrubuteOptionFactory $attrOptionFactory + * @param CountryCollectionFactory $countriesFactory * @param AllowedCountries $allowedCountriesReader - * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param StoreManagerInterface $storeManager * @param Share $shareConfig */ public function __construct( - \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory, - \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countriesFactory, - \Magento\Directory\Model\AllowedCountries $allowedCountriesReader, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Customer\Model\Config\Share $shareConfig + OptionCollectionFactory $attrOptionCollectionFactory, + AttrubuteOptionFactory $attrOptionFactory, + CountryCollectionFactory $countriesFactory, + AllowedCountries $allowedCountriesReader, + StoreManagerInterface $storeManager, + CustomerShareConfig $shareConfig ) { $this->countriesFactory = $countriesFactory; $this->allowedCountriesReader = $allowedCountriesReader; @@ -72,19 +81,22 @@ public function __construct( public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->options) { - $allowedCountries = []; $websiteIds = []; if (!$this->shareConfig->isGlobalScope()) { + $allowedCountries = [[]]; + foreach ($this->storeManager->getWebsites() as $website) { $countries = $this->allowedCountriesReader ->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $website->getId()); - $allowedCountries = array_merge($allowedCountries, $countries); + $allowedCountries[] = $countries; foreach ($countries as $countryCode) { $websiteIds[$countryCode][] = $website->getId(); } } + + $allowedCountries = array_unique(array_merge(...$allowedCountries)); } else { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(); } @@ -106,7 +118,7 @@ public function getAllOptions($withEmpty = true, $defaultValues = false) /** * Create Countries Collection with all countries * - * @return \Magento\Directory\Model\ResourceModel\Country\Collection + * @return CountryCollection */ private function createCountriesCollection() { diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index 1a8859d5bd7bf..55c58282bcae4 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CustomerImportExport\Model\Import; use Magento\Customer\Model\ResourceModel\Address\Attribute\Source\CountryWithWebsites as CountryWithWebsitesSource; @@ -224,7 +225,11 @@ class Address extends AbstractCustomer * @array */ protected $validColumnNames = [ - "region_id", "vat_is_valid", "vat_request_date", "vat_request_id", "vat_request_success" + "region_id", + "vat_is_valid", + "vat_request_date", + "vat_request_id", + "vat_request_success" ]; /** @@ -507,11 +512,12 @@ public function validateData() protected function _importData() { //Preparing data for mass validation/import. - $rows = []; + $rows = [[]]; while ($bunch = $this->_dataSourceModel->getNextBunch()) { - $rows = array_merge($rows, $bunch); + $rows[] = $bunch; } - $this->prepareCustomerData($rows); + + $this->prepareCustomerData(array_merge(...$rows)); unset($bunch, $rows); $this->_dataSourceModel->getIterator()->rewind(); @@ -586,7 +592,7 @@ protected function _mergeEntityAttributes(array $newAttributes, array $attribute * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function _prepareDataForUpdate(array $rowData):array + protected function _prepareDataForUpdate(array $rowData): array { $email = strtolower($rowData[self::COLUMN_EMAIL]); $customerId = $this->_getCustomerId($email, $rowData[self::COLUMN_WEBSITE]); @@ -636,7 +642,7 @@ protected function _prepareDataForUpdate(array $rowData):array if ($attributeParams['is_static']) { $entityRow[$attributeAlias] = $value; } else { - $attributes[$attributeParams['table']][$addressId][$attributeParams['id']]= $value; + $attributes[$attributeParams['table']][$addressId][$attributeParams['id']] = $value; } } } diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php index f86ebaea69730..92b94304186ea 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -500,8 +500,8 @@ protected function _importData() { while ($bunch = $this->_dataSourceModel->getNextBunch()) { $this->prepareCustomerData($bunch); - $entitiesToCreate = []; - $entitiesToUpdate = []; + $entitiesToCreate = [[]]; + $entitiesToUpdate = [[]]; $entitiesToDelete = []; $attributesToSave = []; @@ -521,10 +521,10 @@ protected function _importData() ); } elseif ($this->getBehavior($rowData) == \Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE) { $processedData = $this->_prepareDataForUpdate($rowData); - // phpcs:disable Magento2.Performance.ForeachArrayMerge - $entitiesToCreate = array_merge($entitiesToCreate, $processedData[self::ENTITIES_TO_CREATE_KEY]); - $entitiesToUpdate = array_merge($entitiesToUpdate, $processedData[self::ENTITIES_TO_UPDATE_KEY]); - // phpcs:enable + + $entitiesToCreate[] = $processedData[self::ENTITIES_TO_CREATE_KEY]; + $entitiesToUpdate[] = $processedData[self::ENTITIES_TO_UPDATE_KEY]; + foreach ($processedData[self::ATTRIBUTES_TO_SAVE_KEY] as $tableName => $customerAttributes) { if (!isset($attributesToSave[$tableName])) { $attributesToSave[$tableName] = []; @@ -534,6 +534,10 @@ protected function _importData() } } } + + $entitiesToCreate = array_merge(...$entitiesToCreate); + $entitiesToUpdate = array_merge(...$entitiesToUpdate); + $this->updateItemsCounterStats($entitiesToCreate, $entitiesToUpdate, $entitiesToDelete); /** * Save prepared data diff --git a/app/code/Magento/Deploy/Package/Package.php b/app/code/Magento/Deploy/Package/Package.php index 423f3072c4620..4821d32454675 100644 --- a/app/code/Magento/Deploy/Package/Package.php +++ b/app/code/Magento/Deploy/Package/Package.php @@ -443,12 +443,11 @@ public function getResultMap() */ public function getParentMap() { - $map = []; + $map = [[]]; foreach ($this->getParentPackages() as $parentPackage) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge - $map = array_merge($map, $parentPackage->getMap()); + $map[] = $parentPackage->getMap(); } - return $map; + return array_merge(...$map); } /** @@ -462,10 +461,8 @@ public function getParentFiles($type = null) $files = [[]]; foreach ($this->getParentPackages() as $parentPackage) { if ($type === null) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge $files[] = $parentPackage->getFiles(); } else { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge $files[] = $parentPackage->getFilesByType($type); } } diff --git a/app/code/Magento/Deploy/Package/Processor/PreProcessor/Css.php b/app/code/Magento/Deploy/Package/Processor/PreProcessor/Css.php index b3461e3ab4a22..42775a2e2f6bf 100644 --- a/app/code/Magento/Deploy/Package/Processor/PreProcessor/Css.php +++ b/app/code/Magento/Deploy/Package/Processor/PreProcessor/Css.php @@ -3,12 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Deploy\Package\Processor\PreProcessor; use Magento\Deploy\Console\DeployStaticOptions; use Magento\Deploy\Package\Package; use Magento\Deploy\Package\PackageFile; use Magento\Deploy\Package\Processor\ProcessorInterface; +use Magento\Framework\Css\PreProcessor\Instruction\Import; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\App\Filesystem\DirectoryList; @@ -92,8 +94,7 @@ public function process(Package $package, array $options) } /** - * Checks if there are imports of CSS files or images within the given CSS file - * which exists in the current package + * Checks if there are imports of CSS files or images within the given CSS file which exists in the current package * * @param PackageFile $parentFile * @param Package $package @@ -126,6 +127,7 @@ private function hasOverrides(PackageFile $parentFile, Package $package) * @param string $filePath * @param string $fullPath * @return void + * phpcs:disable Magento2.Functions.DiscouragedFunction */ private function buildMap($packagePath, $filePath, $fullPath) { @@ -141,11 +143,7 @@ private function buildMap($packagePath, $filePath, $fullPath) $packagePath . '/' . pathinfo($filePath, PATHINFO_DIRNAME) . '/' . $matchContent['path'] ); }; - preg_replace_callback( - \Magento\Framework\Css\PreProcessor\Instruction\Import::REPLACE_PATTERN, - $callback, - $content - ); + preg_replace_callback(Import::REPLACE_PATTERN, $callback, $content); preg_match_all(CssResolver::REGEX_CSS_RELATIVE_URLS, $content, $matches); if (!empty($matches[0]) && !empty($matches[1])) { @@ -177,6 +175,7 @@ private function buildMap($packagePath, $filePath, $fullPath) * * @param string $fileName * @return array + * phpcs:disable Magento2.Performance.ForeachArrayMerge */ private function collectFileMap($fileName) { diff --git a/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php b/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php index 323b8e1016291..9e473ccaa2d92 100644 --- a/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php +++ b/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php @@ -6,7 +6,12 @@ namespace Magento\Developer\Console\Command; +use Magento\Developer\Model\XmlCatalog\Format\FormatInterface; +use Magento\Framework\App\Utility\Files; +use Magento\Framework\Config\Dom\UrnResolver; +use Magento\Framework\Console\Cli; use Magento\Framework\Exception\InputException; +use Magento\Framework\Filesystem\Directory\ReadFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -34,37 +39,37 @@ class XmlCatalogGenerateCommand extends Command const IDE_FILE_PATH_ARGUMENT = 'path'; /** - * @var \Magento\Framework\App\Utility\Files + * @var Files */ private $filesUtility; /** - * @var \Magento\Framework\Config\Dom\UrnResolver + * @var UrnResolver */ private $urnResolver; /** - * @var \Magento\Framework\Filesystem\Directory\ReadFactory + * @var ReadFactory */ private $readFactory; /** * Supported formats * - * @var \Magento\Developer\Model\XmlCatalog\Format\FormatInterface[] + * @var FormatInterface[] */ private $formats; /** - * @param \Magento\Framework\App\Utility\Files $filesUtility - * @param \Magento\Framework\Config\Dom\UrnResolver $urnResolver - * @param \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory - * @param \Magento\Developer\Model\XmlCatalog\Format\FormatInterface[] $formats + * @param Files $filesUtility + * @param UrnResolver $urnResolver + * @param ReadFactory $readFactory + * @param FormatInterface[] $formats */ public function __construct( - \Magento\Framework\App\Utility\Files $filesUtility, - \Magento\Framework\Config\Dom\UrnResolver $urnResolver, - \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory, + Files $filesUtility, + UrnResolver $urnResolver, + ReadFactory $readFactory, array $formats = [] ) { $this->filesUtility = $filesUtility; @@ -75,7 +80,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function configure() { @@ -86,7 +91,7 @@ protected function configure() self::IDE_OPTION, null, InputOption::VALUE_REQUIRED, - 'Format in which catalog will be generated. Supported: ['. + 'Format in which catalog will be generated. Supported: [' . implode(', ', $this->getSupportedFormats()) . ']', 'phpstorm' ), @@ -111,19 +116,21 @@ private function getUrnDictionary(OutputInterface $output) $files = $this->filesUtility->getXmlCatalogFiles('*.xml'); $files = array_merge($files, $this->filesUtility->getXmlCatalogFiles('*.xsd')); - $urns = []; + $urns = [[]]; foreach ($files as $file) { + // phpcs:ignore Magento2.Functions.DiscouragedFunction $fileDir = dirname($file[0]); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $fileName = basename($file[0]); $read = $this->readFactory->create($fileDir); $content = $read->readFile($fileName); $matches = []; preg_match_all('/schemaLocation="(urn\:magento\:[^"]*)"/i', $content, $matches); if (isset($matches[1])) { - $urns = array_merge($urns, $matches[1]); + $urns[] = $matches[1]; } } - $urns = array_unique($urns); + $urns = array_unique(array_merge(...$urns)); $paths = []; foreach ($urns as $urn) { try { @@ -139,27 +146,32 @@ private function getUrnDictionary(OutputInterface $output) } /** - * {@inheritdoc} + * @inheritdoc + * * @throws \InvalidArgumentException */ protected function execute(InputInterface $input, OutputInterface $output) { $ideName = $input->getOption(self::IDE_OPTION); - $ideFilePath = $input->getArgument(self::IDE_FILE_PATH_ARGUMENT); + $ideFilePath = $input->getArgument(self::IDE_FILE_PATH_ARGUMENT); $urnDictionary = $this->getUrnDictionary($output); - if ($formatter = $this->getFormatters($ideName)) { - $formatter->generateCatalog($urnDictionary, $ideFilePath); - } else { + + $formatter = $this->getFormatters($ideName); + if (!$formatter instanceof FormatInterface) { throw new InputException(__("Format for IDE '%1' is not supported", $ideName)); } + + $formatter->generateCatalog($urnDictionary, $ideFilePath); + + return Cli::RETURN_SUCCESS; } /** * Get formatter based on format * * @param string $format - * @return \Magento\Developer\Model\XmlCatalog\Format\FormatInterface|false + * @return FormatInterface|false */ private function getFormatters($format) { diff --git a/app/code/Magento/Directory/Model/AllowedCountries.php b/app/code/Magento/Directory/Model/AllowedCountries.php index b9f2d829dd1a6..2ceeb70ba5b01 100644 --- a/app/code/Magento/Directory/Model/AllowedCountries.php +++ b/app/code/Magento/Directory/Model/AllowedCountries.php @@ -62,13 +62,11 @@ public function getAllowedCountries( switch ($scope) { case ScopeInterface::SCOPE_WEBSITES: case ScopeInterface::SCOPE_STORES: - $allowedCountries = []; + $allowedCountries = [[]]; foreach ($scopeCode as $singleFilter) { - $allowedCountries = array_merge( - $allowedCountries, - $this->getCountriesFromConfig($this->getSingleScope($scope), $singleFilter) - ); + $allowedCountries[] = $this->getCountriesFromConfig($this->getSingleScope($scope), $singleFilter); } + $allowedCountries = array_merge(...$allowedCountries); break; default: $allowedCountries = $this->getCountriesFromConfig($scope, $scopeCode); diff --git a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Options/Options.php b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Options/Options.php index 7af7bf447c45a..69f417e1ea732 100644 --- a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Options/Options.php +++ b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Options/Options.php @@ -152,10 +152,10 @@ protected function _prepareOptionValues( $inputType = ''; } - $values = []; + $values = [[]]; $isSystemAttribute = is_array($optionCollection); if ($isSystemAttribute) { - $values = $this->getPreparedValues($optionCollection, $isSystemAttribute, $inputType, $defaultValues); + $values[] = $this->getPreparedValues($optionCollection, $isSystemAttribute, $inputType, $defaultValues); } else { $optionCollection->setPageSize(200); $pageCount = $optionCollection->getLastPageNumber(); @@ -163,15 +163,12 @@ protected function _prepareOptionValues( while ($currentPage <= $pageCount) { $optionCollection->clear(); $optionCollection->setCurPage($currentPage); - $values = array_merge( - $values, - $this->getPreparedValues($optionCollection, $isSystemAttribute, $inputType, $defaultValues) - ); + $values[] = $this->getPreparedValues($optionCollection, $isSystemAttribute, $inputType, $defaultValues); $currentPage++; } } - return $values; + return array_merge(...$values); } /** diff --git a/app/code/Magento/Eav/Model/Form.php b/app/code/Magento/Eav/Model/Form.php index a34b53eede354..074c6cf46a2f4 100644 --- a/app/code/Magento/Eav/Model/Form.php +++ b/app/code/Magento/Eav/Model/Form.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Eav\Model; use Magento\Framework\App\RequestInterface; @@ -10,6 +11,7 @@ /** * EAV Entity Form Model * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -274,8 +276,8 @@ public function getStore() /** * Return current form code * - * @throws \Magento\Framework\Exception\LocalizedException * @return string + * @throws \Magento\Framework\Exception\LocalizedException */ public function getFormCode() { @@ -303,8 +305,8 @@ public function getEntityType() /** * Return current entity instance * - * @throws \Magento\Framework\Exception\LocalizedException * @return \Magento\Framework\Model\AbstractModel + * @throws \Magento\Framework\Exception\LocalizedException */ public function getEntity() { @@ -485,11 +487,11 @@ public function validateData(array $data) { $validator = $this->_getValidator($data); if (!$validator->isValid($this->getEntity())) { - $messages = []; + $messages = [[]]; foreach ($validator->getMessages() as $errorMessages) { - $messages = array_merge($messages, (array)$errorMessages); + $messages[] = (array)$errorMessages; } - return $messages; + return array_merge(...$messages); } return true; } diff --git a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/CompositeFieldProvider.php b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/CompositeFieldProvider.php index 8038c8c05bc1c..b276b67ff7fba 100644 --- a/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/CompositeFieldProvider.php +++ b/app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/CompositeFieldProvider.php @@ -40,12 +40,12 @@ public function __construct(array $providers) */ public function getFields(array $context = []): array { - $allAttributes = []; + $allAttributes = [[]]; foreach ($this->providers as $provider) { - $allAttributes = array_merge($allAttributes, $provider->getFields($context)); + $allAttributes[] = $provider->getFields($context); } - return $allAttributes; + return array_merge(...$allAttributes); } } diff --git a/app/code/Magento/GroupedProduct/Block/Cart/Item/Renderer/Grouped.php b/app/code/Magento/GroupedProduct/Block/Cart/Item/Renderer/Grouped.php index e85d4eeca730a..197be38fb7f5f 100644 --- a/app/code/Magento/GroupedProduct/Block/Cart/Item/Renderer/Grouped.php +++ b/app/code/Magento/GroupedProduct/Block/Cart/Item/Renderer/Grouped.php @@ -45,10 +45,10 @@ public function getGroupedProduct() */ public function getIdentities() { - $identities = parent::getIdentities(); + $identities = [parent::getIdentities()]; if ($this->getItem()) { - $identities = array_merge($identities, $this->getGroupedProduct()->getIdentities()); + $identities[] = $this->getGroupedProduct()->getIdentities(); } - return $identities; + return array_merge(...$identities); } } diff --git a/app/code/Magento/GroupedProduct/Block/Stockqty/Type/Grouped.php b/app/code/Magento/GroupedProduct/Block/Stockqty/Type/Grouped.php index f666cf8d90af9..97dc90ec93493 100644 --- a/app/code/Magento/GroupedProduct/Block/Stockqty/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Block/Stockqty/Type/Grouped.php @@ -32,10 +32,10 @@ protected function _getChildProducts() */ public function getIdentities() { - $identities = []; + $identities = [[]]; foreach ($this->getChildProducts() as $item) { - $identities = array_merge($identities, $item->getIdentities()); + $identities[] = $item->getIdentities(); } - return $identities; + return array_merge(...$identities); } } diff --git a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php index 028bf2c464d4b..eed98c10704ad 100644 --- a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php +++ b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php @@ -237,16 +237,12 @@ public function hasFatalExceptions() */ public function getAllErrors() { - $result = []; if (empty($this->items)) { - return $result; - } - - foreach (array_values($this->items['rows']) as $errors) { - $result = array_merge($result, $errors); + return []; } - return $result; + $errors = array_values($this->items['rows']); + return array_merge(...$errors); } /** @@ -257,14 +253,14 @@ public function getAllErrors() */ public function getErrorsByCode(array $codes) { - $result = []; + $result = [[]]; foreach ($codes as $code) { if (isset($this->items['codes'][$code])) { - $result = array_merge($result, $this->items['codes'][$code]); + $result[] = $this->items['codes'][$code]; } } - return $result; + return array_merge(...$result); } /** diff --git a/app/code/Magento/Integration/Block/Adminhtml/Integration/Activate/Permissions/Tab/Webapi.php b/app/code/Magento/Integration/Block/Adminhtml/Integration/Activate/Permissions/Tab/Webapi.php index 3c719a5814615..2d323fea34e7d 100644 --- a/app/code/Magento/Integration/Block/Adminhtml/Integration/Activate/Permissions/Tab/Webapi.php +++ b/app/code/Magento/Integration/Block/Adminhtml/Integration/Activate/Permissions/Tab/Webapi.php @@ -105,7 +105,7 @@ protected function _construct() } /** - * {@inheritdoc} + * @inheritdoc */ public function canShowTab() { @@ -116,7 +116,7 @@ public function canShowTab() } /** - * {@inheritdoc} + * @inheritdoc * * @codeCoverageIgnore */ @@ -126,7 +126,7 @@ public function getTabLabel() } /** - * {@inheritdoc} + * @inheritdoc * * @codeCoverageIgnore */ @@ -136,7 +136,7 @@ public function getTabTitle() } /** - * {@inheritdoc} + * @inheritdoc * * @codeCoverageIgnore */ @@ -222,13 +222,13 @@ public function isTreeEmpty() */ protected function _getAllResourceIds(array $resources) { - $resourceIds = []; + $resourceIds = [[]]; foreach ($resources as $resource) { - $resourceIds[] = $resource['id']; + $resourceIds[] = [$resource['id']]; if (isset($resource['children'])) { - $resourceIds = array_merge($resourceIds, $this->_getAllResourceIds($resource['children'])); + $resourceIds[] = $this->_getAllResourceIds($resource['children']); } } - return $resourceIds; + return array_merge(...$resourceIds); } } diff --git a/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php b/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php index 88619673ad425..8c6f9fb543d84 100644 --- a/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php +++ b/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php @@ -71,7 +71,7 @@ public function afterGenerateXml(\Magento\Framework\View\Layout $subject, $resul public function afterGetOutput(\Magento\Framework\View\Layout $subject, $result) { if ($subject->isCacheable() && $this->config->isEnabled()) { - $tags = []; + $tags = [[]]; foreach ($subject->getAllBlocks() as $block) { if ($block instanceof \Magento\Framework\DataObject\IdentityInterface) { $isEsiBlock = $block->getTtl() > 0; @@ -80,10 +80,10 @@ public function afterGetOutput(\Magento\Framework\View\Layout $subject, $result) continue; } // phpcs:ignore - $tags = array_merge($tags, $block->getIdentities()); + $tags[] = $block->getIdentities(); } } - $tags = array_unique($tags); + $tags = array_unique(array_merge(...$tags)); $this->response->setHeader('X-Magento-Tags', implode(',', $tags)); } return $result; diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php index 8ea97d31ed4d9..f96c08a9605a8 100644 --- a/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Payment\Gateway\Validator; use Magento\Framework\ObjectManager\TMap; @@ -57,26 +58,25 @@ public function __construct( public function validate(array $validationSubject) { $isValid = true; - $failsDescriptionAggregate = []; - $errorCodesAggregate = []; + $failsDescriptionAggregate = [[]]; + $errorCodesAggregate = [[]]; foreach ($this->validators as $key => $validator) { $result = $validator->validate($validationSubject); if (!$result->isValid()) { $isValid = false; - $failsDescriptionAggregate = array_merge( - $failsDescriptionAggregate, - $result->getFailsDescription() - ); - $errorCodesAggregate = array_merge( - $errorCodesAggregate, - $result->getErrorCodes() - ); + $failsDescriptionAggregate[] = $result->getFailsDescription(); + $errorCodesAggregate[] = $result->getErrorCodes(); + if (!empty($this->chainBreakingValidators[$key])) { break; } } } - return $this->createResult($isValid, $failsDescriptionAggregate, $errorCodesAggregate); + return $this->createResult( + $isValid, + array_merge(...$failsDescriptionAggregate), + array_merge(...$errorCodesAggregate) + ); } } diff --git a/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php index f1c414e6faa9b..61410499e956e 100644 --- a/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php +++ b/app/code/Magento/Paypal/Model/Config/Structure/PaymentSectionModifier.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Paypal\Model\Config\Structure; /** @@ -60,9 +61,9 @@ public function modify(array $initialStructure) unset($childData['children'][$moveInstruction['section']]); unset($moveInstruction['data']['displayIn']); $changedStructure - [$moveInstruction['parent']] - ['children'] - [$moveInstruction['section']] = $moveInstruction['data']; + [$moveInstruction['parent']] + ['children'] + [$moveInstruction['section']] = $moveInstruction['data']; } } if (!isset($moveInstructions[$childSection])) { @@ -83,7 +84,7 @@ public function modify(array $initialStructure) */ private function getMoveInstructions($section, $data) { - $moved = []; + $moved = [[]]; if (array_key_exists('children', $data)) { foreach ($data['children'] as $childSection => $childData) { @@ -91,23 +92,20 @@ private function getMoveInstructions($section, $data) if (isset($movedChildren[$childSection])) { unset($data['children'][$childSection]); } - $moved = array_merge($moved, $movedChildren); + $moved[] = $movedChildren; } } if (isset($data['displayIn']) && in_array($data['displayIn'], self::$specialGroups)) { - $moved = array_merge( - [ - $section => [ + $moved[] = [ + $section => [ 'parent' => $data['displayIn'], 'section' => $section, 'data' => $data - ] - ], - $moved - ); + ] + ]; } - return $moved; + return array_merge(...$moved); } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/BuyRequestBuilder.php b/app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/BuyRequestBuilder.php index 90f32e96a5fde..c14cc1324732c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/BuyRequestBuilder.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/BuyRequestBuilder.php @@ -45,11 +45,11 @@ public function __construct( */ public function build(array $cartItemData): DataObject { - $requestData = []; + $requestData = [[]]; foreach ($this->providers as $provider) { - $requestData = array_merge($requestData, $provider->execute($cartItemData)); + $requestData[] = $provider->execute($cartItemData); } - return $this->dataObjectFactory->create(['data' => $requestData]); + return $this->dataObjectFactory->create(['data' => array_merge(...$requestData)]); } } diff --git a/app/code/Magento/Reports/Block/Product/Viewed.php b/app/code/Magento/Reports/Block/Product/Viewed.php index 5f9fdf8533523..ba4d03182213a 100644 --- a/app/code/Magento/Reports/Block/Product/Viewed.php +++ b/app/code/Magento/Reports/Block/Product/Viewed.php @@ -59,8 +59,7 @@ public function getCount() } /** - * Prepare to html - * check has viewed products + * Prepare to html check has viewed products * * @return string */ @@ -77,10 +76,10 @@ protected function _toHtml() */ public function getIdentities() { - $identities = []; + $identities = [[]]; foreach ($this->getItemsCollection() as $item) { - $identities = array_merge($identities, $item->getIdentities()); + $identities[] = $item->getIdentities(); } - return $identities; + return array_merge(...$identities); } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Items/Column/DefaultColumn.php b/app/code/Magento/Sales/Block/Adminhtml/Items/Column/DefaultColumn.php index 80dcce2fd1be4..efef617acf900 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Items/Column/DefaultColumn.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Items/Column/DefaultColumn.php @@ -68,19 +68,19 @@ public function getItem() */ public function getOrderOptions() { - $result = []; + $result = [[]]; if ($options = $this->getItem()->getProductOptions()) { if (isset($options['options'])) { - $result = array_merge($result, $options['options']); + $result[] = $options['options']; } if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); + $result[] = $options['additional_options']; } if (!empty($options['attributes_info'])) { - $result = array_merge($options['attributes_info'], $result); + $result[] = $options['attributes_info']; } } - return $result; + return array_merge(...$result); } /** diff --git a/app/code/Magento/Sales/Block/Order/Email/Items/DefaultItems.php b/app/code/Magento/Sales/Block/Order/Email/Items/DefaultItems.php index 0aa4f807700b6..064405daf89a8 100644 --- a/app/code/Magento/Sales/Block/Order/Email/Items/DefaultItems.php +++ b/app/code/Magento/Sales/Block/Order/Email/Items/DefaultItems.php @@ -29,27 +29,31 @@ public function getOrder() } /** + * Returns Items options as array + * * @return array */ public function getItemOptions() { - $result = []; + $result = [[]]; if ($options = $this->getItem()->getOrderItem()->getProductOptions()) { if (isset($options['options'])) { - $result = array_merge($result, $options['options']); + $result[] = $options['options']; } if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); + $result[] = $options['additional_options']; } if (isset($options['attributes_info'])) { - $result = array_merge($result, $options['attributes_info']); + $result[] = $options['attributes_info']; } } - return $result; + return array_merge(...$result); } /** + * Formats the value in HTML + * * @param string|array $value * @return string */ @@ -70,7 +74,9 @@ public function getValueHtml($value) } /** - * @param mixed $item + * Returns Product SKU for Item provided + * + * @param OrderItem $item * @return mixed */ public function getSku($item) diff --git a/app/code/Magento/Sales/Block/Order/Email/Items/Order/DefaultOrder.php b/app/code/Magento/Sales/Block/Order/Email/Items/Order/DefaultOrder.php index ae2dec6aefa6e..0291a1275c350 100644 --- a/app/code/Magento/Sales/Block/Order/Email/Items/Order/DefaultOrder.php +++ b/app/code/Magento/Sales/Block/Order/Email/Items/Order/DefaultOrder.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Block\Order\Email\Items\Order; use Magento\Sales\Model\Order\Item as OrderItem; @@ -27,48 +28,49 @@ public function getOrder() } /** + * Returns array of Item options + * * @return array */ public function getItemOptions() { - $result = []; + $result = [[]]; if ($options = $this->getItem()->getProductOptions()) { if (isset($options['options'])) { - $result = array_merge($result, $options['options']); + $result[] = $options['options']; } if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); + $result[] = $options['additional_options']; } if (isset($options['attributes_info'])) { - $result = array_merge($result, $options['attributes_info']); + $result[] = $options['attributes_info']; } } - return $result; + return array_merge(...$result); } /** + * Formats the value in HTML + * * @param string|array $value * @return string */ public function getValueHtml($value) { if (is_array($value)) { - return sprintf( - '%d', - $value['qty'] - ) . ' x ' . $this->escapeHtml( - $value['title'] - ) . " " . $this->getItem()->getOrder()->formatPrice( - $value['price'] - ); + return sprintf('%d', $value['qty']) + . ' x ' . $this->escapeHtml($value['title']) + . " " . $this->getItem()->getOrder()->formatPrice($value['price']); } else { return $this->escapeHtml($value); } } /** - * @param mixed $item + * Returns Product SKU for Item provided + * + * @param OrderItem $item * @return mixed */ public function getSku($item) diff --git a/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php b/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php index 2e119d0bf887a..bca6d49760d9a 100644 --- a/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php +++ b/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php @@ -6,7 +6,12 @@ namespace Magento\Sales\Block\Order\Item\Renderer; -use Magento\Sales\Model\Order\CreditMemo\Item as CreditMemoItem; +use Magento\Catalog\Model\Product\OptionFactory; +use Magento\Framework\DataObject; +use Magento\Framework\Stdlib\StringUtils; +use Magento\Framework\View\Element\AbstractBlock; +use Magento\Framework\View\Element\Template\Context; +use Magento\Sales\Model\Order\Creditmemo\Item as CreditMemoItem; use Magento\Sales\Model\Order\Invoice\Item as InvoiceItem; use Magento\Sales\Model\Order\Item as OrderItem; @@ -21,25 +26,25 @@ class DefaultRenderer extends \Magento\Framework\View\Element\Template /** * Magento string lib * - * @var \Magento\Framework\Stdlib\StringUtils + * @var StringUtils */ protected $string; /** - * @var \Magento\Catalog\Model\Product\OptionFactory + * @var OptionFactory */ protected $_productOptionFactory; /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Framework\Stdlib\StringUtils $string - * @param \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory + * @param Context $context + * @param StringUtils $string + * @param OptionFactory $productOptionFactory * @param array $data */ public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Framework\Stdlib\StringUtils $string, - \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory, + Context $context, + StringUtils $string, + OptionFactory $productOptionFactory, array $data = [] ) { $this->string = $string; @@ -50,10 +55,10 @@ public function __construct( /** * Set item. * - * @param \Magento\Framework\DataObject $item + * @param DataObject $item * @return $this */ - public function setItem(\Magento\Framework\DataObject $item) + public function setItem(DataObject $item) { $this->setData('item', $item); return $this; @@ -86,7 +91,7 @@ public function getOrder() */ public function getOrderItem() { - if ($this->getItem() instanceof \Magento\Sales\Model\Order\Item) { + if ($this->getItem() instanceof OrderItem) { return $this->getItem(); } else { return $this->getItem()->getOrderItem(); @@ -100,20 +105,20 @@ public function getOrderItem() */ public function getItemOptions() { - $result = []; + $result = [[]]; $options = $this->getOrderItem()->getProductOptions(); if ($options) { if (isset($options['options'])) { - $result = array_merge($result, $options['options']); + $result[] = $options['options']; } if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); + $result[] = $options['additional_options']; } if (isset($options['attributes_info'])) { - $result = array_merge($result, $options['attributes_info']); + $result[] = $options['attributes_info']; } } - return $result; + return array_merge(...$result); } /** diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php index 422ff1746c9a6..29e011217ef20 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php @@ -6,41 +6,54 @@ namespace Magento\Sales\Model\Order\Pdf\Items; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\DataObject; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\Filter\FilterManager; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\Context; +use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\Registry; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Pdf\AbstractPdf; +use Magento\Tax\Helper\Data as TaxHelper; /** * Sales Order Pdf Items renderer Abstract * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ -abstract class AbstractItems extends \Magento\Framework\Model\AbstractModel +abstract class AbstractItems extends AbstractModel { /** * Order model * - * @var \Magento\Sales\Model\Order + * @var Order */ protected $_order; /** * Source model (invoice, shipment, creditmemo) * - * @var \Magento\Framework\Model\AbstractModel + * @var AbstractModel */ protected $_source; /** * Item object * - * @var \Magento\Framework\DataObject + * @var DataObject */ protected $_item; /** * Pdf object * - * @var \Magento\Sales\Model\Order\Pdf\AbstractPdf + * @var AbstractPdf */ protected $_pdf; @@ -54,38 +67,38 @@ abstract class AbstractItems extends \Magento\Framework\Model\AbstractModel /** * Tax data * - * @var \Magento\Tax\Helper\Data + * @var TaxHelper */ protected $_taxData; /** - * @var \Magento\Framework\Filesystem\Directory\ReadInterface + * @var ReadInterface */ protected $_rootDirectory; /** - * @var \Magento\Framework\Filter\FilterManager + * @var FilterManager */ protected $filterManager; /** - * @param \Magento\Framework\Model\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Magento\Tax\Helper\Data $taxData - * @param \Magento\Framework\Filesystem $filesystem , - * @param \Magento\Framework\Filter\FilterManager $filterManager - * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection + * @param Context $context + * @param Registry $registry + * @param TaxHelper $taxData + * @param Filesystem $filesystem , + * @param FilterManager $filterManager + * @param AbstractResource $resource + * @param AbstractDb $resourceCollection * @param array $data */ public function __construct( - \Magento\Framework\Model\Context $context, - \Magento\Framework\Registry $registry, - \Magento\Tax\Helper\Data $taxData, - \Magento\Framework\Filesystem $filesystem, - \Magento\Framework\Filter\FilterManager $filterManager, - \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, + Context $context, + Registry $registry, + TaxHelper $taxData, + Filesystem $filesystem, + FilterManager $filterManager, + AbstractResource $resource = null, + AbstractDb $resourceCollection = null, array $data = [] ) { $this->filterManager = $filterManager; @@ -97,10 +110,10 @@ public function __construct( /** * Set order model * - * @param \Magento\Sales\Model\Order $order + * @param Order $order * @return $this */ - public function setOrder(\Magento\Sales\Model\Order $order) + public function setOrder(Order $order) { $this->_order = $order; return $this; @@ -109,10 +122,10 @@ public function setOrder(\Magento\Sales\Model\Order $order) /** * Set Source model * - * @param \Magento\Framework\Model\AbstractModel $source + * @param AbstractModel $source * @return $this */ - public function setSource(\Magento\Framework\Model\AbstractModel $source) + public function setSource(AbstractModel $source) { $this->_source = $source; return $this; @@ -121,10 +134,10 @@ public function setSource(\Magento\Framework\Model\AbstractModel $source) /** * Set item object * - * @param \Magento\Framework\DataObject $item + * @param DataObject $item * @return $this */ - public function setItem(\Magento\Framework\DataObject $item) + public function setItem(DataObject $item) { $this->_item = $item; return $this; @@ -133,10 +146,10 @@ public function setItem(\Magento\Framework\DataObject $item) /** * Set Pdf model * - * @param \Magento\Sales\Model\Order\Pdf\AbstractPdf $pdf + * @param AbstractPdf $pdf * @return $this */ - public function setPdf(\Magento\Sales\Model\Order\Pdf\AbstractPdf $pdf) + public function setPdf(AbstractPdf $pdf) { $this->_pdf = $pdf; return $this; @@ -313,20 +326,20 @@ public function getItemPricesForDisplay() */ public function getItemOptions() { - $result = []; + $result = [[]]; $options = $this->getItem()->getOrderItem()->getProductOptions(); if ($options) { if (isset($options['options'])) { - $result = array_merge($result, $options['options']); + $result[] = $options['options']; } if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); + $result[] = $options['additional_options']; } if (isset($options['attributes_info'])) { - $result = array_merge($result, $options['attributes_info']); + $result[] = $options['attributes_info']; } } - return $result; + return array_merge(...$result); } /** diff --git a/app/code/Magento/Sales/Model/ResourceModel/Provider/NotSyncedDataProvider.php b/app/code/Magento/Sales/Model/ResourceModel/Provider/NotSyncedDataProvider.php index aa2ac20f8f55c..645e411b80b67 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Provider/NotSyncedDataProvider.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Provider/NotSyncedDataProvider.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Model\ResourceModel\Provider; use Magento\Framework\ObjectManager\TMapFactory; @@ -21,10 +22,8 @@ class NotSyncedDataProvider implements NotSyncedDataProviderInterface * @param TMapFactory $tmapFactory * @param array $providers */ - public function __construct( - TMapFactory $tmapFactory, - array $providers = [] - ) { + public function __construct(TMapFactory $tmapFactory, array $providers = []) + { $this->providers = $tmapFactory->create( [ 'array' => $providers, @@ -38,11 +37,11 @@ public function __construct( */ public function getIds($mainTableName, $gridTableName) { - $result = []; + $result = [[]]; foreach ($this->providers as $provider) { - $result = array_merge($result, $provider->getIds($mainTableName, $gridTableName)); + $result[] = $provider->getIds($mainTableName, $gridTableName); } - return array_unique($result); + return array_unique(array_merge(...$result)); } } diff --git a/app/code/Magento/Search/Model/Autocomplete.php b/app/code/Magento/Search/Model/Autocomplete.php index b50cd330d5d95..45957e8795744 100644 --- a/app/code/Magento/Search/Model/Autocomplete.php +++ b/app/code/Magento/Search/Model/Autocomplete.php @@ -5,6 +5,9 @@ */ namespace Magento\Search\Model; +/** + * Provides list of Autocomplete items + */ class Autocomplete implements AutocompleteInterface { /** @@ -23,15 +26,15 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getItems() { - $data = []; + $data = [[]]; foreach ($this->dataProviders as $dataProvider) { - $data = array_merge($data, $dataProvider->getItems()); + $data[] = $dataProvider->getItems(); } - return $data; + return array_merge(...$data); } } diff --git a/app/code/Magento/Search/Model/SynonymGroupRepository.php b/app/code/Magento/Search/Model/SynonymGroupRepository.php index 75d7049afd949..dbc2b66b1f047 100644 --- a/app/code/Magento/Search/Model/SynonymGroupRepository.php +++ b/app/code/Magento/Search/Model/SynonymGroupRepository.php @@ -7,6 +7,7 @@ namespace Magento\Search\Model; use Magento\Framework\Exception\CouldNotDeleteException; +use Magento\Framework\Phrase; use Magento\Search\Api\Data\SynonymGroupInterface; use Magento\Search\Api\SynonymGroupRepositoryInterface; use Magento\Search\Model\ResourceModel\SynonymGroup as SynonymGroupResourceModel; @@ -37,7 +38,7 @@ class SynonymGroupRepository implements SynonymGroupRepositoryInterface * @param SynonymGroupResourceModel $resourceModel */ public function __construct( - \Magento\Search\Model\SynonymGroupFactory $synonymGroupFactory, + SynonymGroupFactory $synonymGroupFactory, SynonymGroupResourceModel $resourceModel ) { $this->synonymGroupFactory = $synonymGroupFactory; @@ -64,8 +65,8 @@ public function save(SynonymGroupInterface $synonymGroup, $errorOnMergeConflict * Deletes a synonym group * * @param SynonymGroupInterface $synonymGroup - * @throws CouldNotDeleteException * @return bool + * @throws CouldNotDeleteException */ public function delete(SynonymGroupInterface $synonymGroup) { @@ -149,17 +150,17 @@ private function create(SynonymGroupInterface $synonymGroup, $errorOnMergeConfli */ private function merge(SynonymGroupInterface $synonymGroupToMerge, array $matchingGroupIds) { - $mergedSynonyms = []; + $mergedSynonyms = [[]]; foreach ($matchingGroupIds as $groupId) { /** @var SynonymGroup $synonymGroupModel */ $synonymGroupModel = $this->synonymGroupFactory->create(); $synonymGroupModel->load($groupId); - $mergedSynonyms = array_merge($mergedSynonyms, explode(',', $synonymGroupModel->getSynonymGroup())); + $mergedSynonyms[] = explode(',', $synonymGroupModel->getSynonymGroup()); $synonymGroupModel->delete(); } - $mergedSynonyms = array_merge($mergedSynonyms, explode(',', $synonymGroupToMerge->getSynonymGroup())); - $mergedSynonyms = array_unique($mergedSynonyms); - return $mergedSynonyms; + $mergedSynonyms[] = explode(',', $synonymGroupToMerge->getSynonymGroup()); + + return array_unique(array_merge(...$mergedSynonyms)); } /** @@ -222,7 +223,7 @@ private function update( * Gets merge conflict exception message * * @param string[] $matchingSynonymGroups - * @return \Magento\Framework\Phrase + * @return Phrase */ private function getExceptionMessage($matchingSynonymGroups) { diff --git a/app/code/Magento/Tax/Model/ResourceModel/Calculation/Rate/Collection.php b/app/code/Magento/Tax/Model/ResourceModel/Calculation/Rate/Collection.php index 9b344f6e96f65..7863b70f6626a 100644 --- a/app/code/Magento/Tax/Model/ResourceModel/Calculation/Rate/Collection.php +++ b/app/code/Magento/Tax/Model/ResourceModel/Calculation/Rate/Collection.php @@ -7,9 +7,25 @@ /** * Tax rate collection */ + namespace Magento\Tax\Model\ResourceModel\Calculation\Rate; -class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; +use Magento\Framework\Data\Collection\EntityFactory; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Tax\Model\Calculation\Rate; +use Magento\Tax\Model\ResourceModel\Calculation\Rate as RateResourceModel; +use Psr\Log\LoggerInterface; + +/** + * Collection of Calculation Rates + */ +class Collection extends AbstractCollection { /** * Value of fetched from DB of rules per cycle @@ -17,27 +33,27 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab const TAX_RULES_CHUNK_SIZE = 1000; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $_storeManager; /** - * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param EntityFactory $entityFactory + * @param LoggerInterface $logger + * @param FetchStrategyInterface $fetchStrategy + * @param ManagerInterface $eventManager + * @param StoreManagerInterface $storeManager * @param mixed $connection - * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource + * @param AbstractDb $resource */ public function __construct( - \Magento\Framework\Data\Collection\EntityFactory $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null + EntityFactory $entityFactory, + LoggerInterface $logger, + FetchStrategyInterface $fetchStrategy, + ManagerInterface $eventManager, + StoreManagerInterface $storeManager, + AdapterInterface $connection = null, + AbstractDb $resource = null ) { $this->_storeManager = $storeManager; parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); @@ -50,10 +66,7 @@ public function __construct( */ protected function _construct() { - $this->_init( - \Magento\Tax\Model\Calculation\Rate::class, - \Magento\Tax\Model\ResourceModel\Calculation\Rate::class - ); + $this->_init(Rate::class, RateResourceModel::class); } /** @@ -90,7 +103,7 @@ public function joinRegionTable() /** * Join rate title for specified store * - * @param \Magento\Store\Model\Store|string|int $store + * @param Store|string|int $store * @return $this */ public function joinTitle($store = null) @@ -170,12 +183,10 @@ public function toOptionHash() } /** - * Convert items array to hash for select options - * using fetchItem method - * - * @see fetchItem() + * Convert items array to hash for select options using fetchItem method * * @return array + * @see fetchItem() */ public function toOptionHashOptimized() { @@ -195,7 +206,7 @@ public function getOptionRates() { $size = self::TAX_RULES_CHUNK_SIZE; $page = 1; - $rates = []; + $rates = [[]]; do { $offset = $size * ($page - 1); $this->getSelect()->reset(); @@ -206,11 +217,11 @@ public function getOptionRates() ) ->limit($size, $offset); - $rates = array_merge($rates, $this->toOptionArray()); + $rates[] = $this->toOptionArray(); $this->clear(); $page++; } while ($this->getSize() > $offset); - return $rates; + return array_merge(...$rates); } } diff --git a/app/code/Magento/Weee/Model/Total/Quote/Weee.php b/app/code/Magento/Weee/Model/Total/Quote/Weee.php index 96a40c9533f8f..449c6cd688668 100644 --- a/app/code/Magento/Weee/Model/Total/Quote/Weee.php +++ b/app/code/Magento/Weee/Model/Total/Quote/Weee.php @@ -7,10 +7,19 @@ namespace Magento\Weee\Model\Total\Quote; use Magento\Framework\Pricing\PriceCurrencyInterface; +use Magento\Quote\Api\Data\ShippingAssignmentInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Address\Total; use Magento\Quote\Model\Quote\Address\Total\AbstractTotal; +use Magento\Quote\Model\Quote\Item\AbstractItem; use Magento\Store\Model\Store; use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector; +use Magento\Weee\Helper\Data as WeeHelper; +/** + * Calculate totals for Quote + */ class Weee extends AbstractTotal { /** @@ -23,7 +32,7 @@ class Weee extends AbstractTotal const ITEM_TYPE = 'weee'; /** - * @var \Magento\Weee\Helper\Data + * @var WeeHelper */ protected $weeeData; @@ -66,11 +75,11 @@ class Weee extends AbstractTotal protected $priceCurrency; /** - * @param \Magento\Weee\Helper\Data $weeeData + * @param WeeHelper $weeeData * @param PriceCurrencyInterface $priceCurrency */ public function __construct( - \Magento\Weee\Helper\Data $weeeData, + WeeHelper $weeeData, PriceCurrencyInterface $priceCurrency ) { $this->priceCurrency = $priceCurrency; @@ -82,15 +91,15 @@ public function __construct( /** * Collect Weee amounts for the quote / order * - * @param \Magento\Quote\Model\Quote $quote - * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment - * @param \Magento\Quote\Model\Quote\Address\Total $total + * @param Quote $quote + * @param ShippingAssignmentInterface $shippingAssignment + * @param Total $total * @return $this */ public function collect( - \Magento\Quote\Model\Quote $quote, - \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment, - \Magento\Quote\Model\Quote\Address\Total $total + Quote $quote, + ShippingAssignmentInterface $shippingAssignment, + Total $total ) { AbstractTotal::collect($quote, $shippingAssignment, $total); $this->_store = $quote->getStore(); @@ -130,16 +139,16 @@ public function collect( /** * Calculate item fixed tax and prepare information for discount and regular taxation * - * @param \Magento\Quote\Model\Quote\Address $address - * @param \Magento\Quote\Model\Quote\Address\Total $total - * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item - * @return void|$this + * @param Address $address + * @param Total $total + * @param AbstractItem $item + * @return void|$this * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ protected function process( - \Magento\Quote\Model\Quote\Address $address, - \Magento\Quote\Model\Quote\Address\Total $total, + Address $address, + Total $total, $item ) { $attributes = $this->weeeData->getProductWeeeAttributes( @@ -248,12 +257,12 @@ protected function process( /** * Process row amount based on FPT total amount configuration setting * - * @param \Magento\Quote\Model\Quote\Address\Total $total - * @param float $rowValueExclTax - * @param float $baseRowValueExclTax - * @param float $rowValueInclTax - * @param float $baseRowValueInclTax - * @return $this + * @param Total $total + * @param float $rowValueExclTax + * @param float $baseRowValueExclTax + * @param float $rowValueInclTax + * @param float $baseRowValueInclTax + * @return $this */ protected function processTotalAmount( $total, @@ -279,8 +288,7 @@ protected function processTotalAmount( } /** - * Increment and return counter. This function is intended to be used to generate temporary - * id for an item. + * Increment and return counter. This function is intended to be used to generate temporary id for an item. * * @return int */ @@ -292,25 +300,26 @@ protected function getNextIncrement() /** * Recalculate parent item amounts based on children results * - * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item - * @return void - * + * @param AbstractItem $item + * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - protected function recalculateParent(\Magento\Quote\Model\Quote\Item\AbstractItem $item) + protected function recalculateParent(AbstractItem $item) { - $associatedTaxables = []; + $associatedTaxables = [[]]; foreach ($item->getChildren() as $child) { - $associatedTaxables = array_merge($associatedTaxables, $child->getAssociatedTaxables()); + $associatedTaxables[] = $child->getAssociatedTaxables(); } - $item->setAssociatedTaxables($associatedTaxables); + $item->setAssociatedTaxables( + array_unique(array_merge(...$associatedTaxables)) + ); } /** * Reset information about Tax and Wee on FPT for shopping cart item * - * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item - * @return void + * @param AbstractItem $item + * @return void */ protected function resetItemData($item) { @@ -332,24 +341,24 @@ protected function resetItemData($item) } /** - * @param \Magento\Quote\Model\Quote $quote - * @param \Magento\Quote\Model\Quote\Address\Total $total + * Return `null` instead of original empty array + * + * @param Quote $quote + * @param Total $total * @return array|null * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total) + public function fetch(Quote $quote, Total $total) { return null; } /** - * Process model configuration array. - * This method can be used for changing totals collect sort order - * - * @param array $config - * @param Store $store - * @return array + * Process model configuration array. This method can be used for changing totals collect sort order * + * @param array $config + * @param Store $store + * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function processConfigArray($config, $store) @@ -360,7 +369,7 @@ public function processConfigArray($config, $store) /** * No aggregated label for fixed product tax * - * TODO: fix + * @TODO: fix * @return string */ public function getLabel() From 882fa18b167c22aef4891d3828639c709b8c0eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Mon, 13 Jan 2020 13:26:32 +0100 Subject: [PATCH 152/666] Code Review changes --- .../CatalogInventory/Model/StockIndex.php | 25 ++++++------ .../Block/Product/ProductsList.php | 5 ++- .../ProcessingErrorAggregator.php | 2 +- .../PageCache/Model/Layout/LayoutPlugin.php | 38 +++++++++++-------- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/StockIndex.php b/app/code/Magento/CatalogInventory/Model/StockIndex.php index af211b98386bd..ad0cff43c6ac9 100644 --- a/app/code/Magento/CatalogInventory/Model/StockIndex.php +++ b/app/code/Magento/CatalogInventory/Model/StockIndex.php @@ -6,15 +6,16 @@ namespace Magento\CatalogInventory\Model; +use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Type as ProductType; use Magento\Catalog\Model\Product\Website as ProductWebsite; -use Magento\Catalog\Model\ProductFactory; use Magento\CatalogInventory\Api\StockIndexInterface; use Magento\CatalogInventory\Model\ResourceModel\Stock\Status as StockStatusResourceModel; use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\Website; /** * Index responsible for Stock @@ -123,7 +124,7 @@ public function updateProductStockStatus($productId, $websiteId) { $item = $this->stockRegistryProvider->getStockItem($productId, $websiteId); - $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK; + $status = Stock\Status::STATUS_IN_STOCK; $qty = 0; if ($item->getItemId()) { $status = $item->getIsInStock(); @@ -147,9 +148,9 @@ protected function processChildren( $productId, $websiteId, $qty = 0, - $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK + $status = Stock\Status::STATUS_IN_STOCK ) { - if ($status == \Magento\CatalogInventory\Model\Stock\Status::STATUS_OUT_OF_STOCK) { + if ($status == Stock\Status::STATUS_OUT_OF_STOCK) { $this->getStockStatusResource()->saveProductStatus($productId, $status, $qty, $websiteId); return; } @@ -158,11 +159,11 @@ protected function processChildren( $websitesWithStores = $this->getWebsitesWithDefaultStores($websiteId); foreach (array_keys($websitesWithStores) as $websiteId) { - /* @var $website \Magento\Store\Model\Website */ + /* @var $website Website */ $statuses[$websiteId] = $status; } - /** @var \Magento\Catalog\Model\Product $product */ + /** @var Product $product */ $product = $this->productRepository->getById($productId); $typeInstance = $product->getTypeInstance(); @@ -187,7 +188,7 @@ protected function processChildren( && in_array($websiteId, $childrenWebsites[$childId]) && $childrenStatus[$childId] == Status::STATUS_ENABLED && isset($childrenStock[$childId]) - && $childrenStock[$childId] == \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK + && $childrenStock[$childId] == Stock\Status::STATUS_IN_STOCK ) { $optionStatus = true; } @@ -206,7 +207,7 @@ protected function processChildren( * Retrieve website models * * @param int|null $websiteId - * @return array + * @return Website[] */ protected function getWebsitesWithDefaultStores($websiteId = null) { @@ -233,19 +234,19 @@ protected function processParents($productId, $websiteId) { $parentIds = [[]]; foreach ($this->getProductTypeInstances() as $typeInstance) { - /* @var $typeInstance AbstractType */ + /* @var ProductType\AbstractType $typeInstance */ $parentIds[] = $typeInstance->getParentIdsByChild($productId); } $parentIds = array_merge(...$parentIds); if (empty($parentIds)) { - return $this; + return; } foreach ($parentIds as $parentId) { $item = $this->stockRegistryProvider->getStockItem($parentId, $websiteId); - $status = \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK; + $status = Stock\Status::STATUS_IN_STOCK; $qty = 0; if ($item->getItemId()) { $status = $item->getIsInStock(); @@ -258,7 +259,7 @@ protected function processParents($productId, $websiteId) /** * Retrieve Product Type Instances as key - type code, value - instance model * - * @return array + * @return ProductType\AbstractType[] */ protected function getProductTypeInstances() { diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php index 22e3a7382cdac..63aaf85245651 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php +++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php @@ -187,7 +187,8 @@ protected function _construct() 'cache_lifetime' => 86400, 'cache_tags' => [ Product::CACHE_TAG, - ], ]); + ], + ]); } /** @@ -208,7 +209,7 @@ public function getCacheKeyInfo() $this->_storeManager->getStore()->getId(), $this->_design->getDesignTheme()->getId(), $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_GROUP), - (int) $this->getRequest()->getParam($this->getData('page_var_name'), 1), + (int)$this->getRequest()->getParam($this->getData('page_var_name'), 1), $this->getProductsPerPage(), $this->getProductsCount(), $conditions, diff --git a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php index eed98c10704ad..5ea6227231543 100644 --- a/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php +++ b/app/code/Magento/ImportExport/Model/Import/ErrorProcessing/ProcessingErrorAggregator.php @@ -237,7 +237,7 @@ public function hasFatalExceptions() */ public function getAllErrors() { - if (empty($this->items)) { + if (empty($this->items) || empty($this->items['rows'])) { return []; } diff --git a/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php b/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php index 8c6f9fb543d84..b4d9cb2d5e076 100644 --- a/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php +++ b/app/code/Magento/PageCache/Model/Layout/LayoutPlugin.php @@ -3,8 +3,15 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\PageCache\Model\Layout; +use Magento\Framework\App\MaintenanceMode; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\DataObject\IdentityInterface; +use Magento\Framework\View\Layout; +use Magento\PageCache\Model\Config; + /** * Class LayoutPlugin * @@ -13,31 +20,31 @@ class LayoutPlugin { /** - * @var \Magento\PageCache\Model\Config + * @var Config */ protected $config; /** - * @var \Magento\Framework\App\ResponseInterface + * @var ResponseInterface */ protected $response; /** - * @var \Magento\Framework\App\MaintenanceMode + * @var MaintenanceMode */ private $maintenanceMode; /** * Constructor * - * @param \Magento\Framework\App\ResponseInterface $response - * @param \Magento\PageCache\Model\Config $config - * @param \Magento\Framework\App\MaintenanceMode $maintenanceMode + * @param ResponseInterface $response + * @param Config $config + * @param MaintenanceMode $maintenanceMode */ public function __construct( - \Magento\Framework\App\ResponseInterface $response, - \Magento\PageCache\Model\Config $config, - \Magento\Framework\App\MaintenanceMode $maintenanceMode + ResponseInterface $response, + Config $config, + MaintenanceMode $maintenanceMode ) { $this->response = $response; $this->config = $config; @@ -49,11 +56,11 @@ public function __construct( * * We have to set public headers in order to tell Varnish and Builtin app that page should be cached * - * @param \Magento\Framework\View\Layout $subject + * @param Layout $subject * @param mixed $result * @return mixed */ - public function afterGenerateXml(\Magento\Framework\View\Layout $subject, $result) + public function afterGenerateXml(Layout $subject, $result) { if ($subject->isCacheable() && !$this->maintenanceMode->isOn() && $this->config->isEnabled()) { $this->response->setPublicHeaders($this->config->getTtl()); @@ -64,22 +71,21 @@ public function afterGenerateXml(\Magento\Framework\View\Layout $subject, $resul /** * Retrieve all identities from blocks for further cache invalidation * - * @param \Magento\Framework\View\Layout $subject + * @param Layout $subject * @param mixed $result * @return mixed */ - public function afterGetOutput(\Magento\Framework\View\Layout $subject, $result) + public function afterGetOutput(Layout $subject, $result) { if ($subject->isCacheable() && $this->config->isEnabled()) { $tags = [[]]; foreach ($subject->getAllBlocks() as $block) { - if ($block instanceof \Magento\Framework\DataObject\IdentityInterface) { + if ($block instanceof IdentityInterface) { $isEsiBlock = $block->getTtl() > 0; - $isVarnish = $this->config->getType() == \Magento\PageCache\Model\Config::VARNISH; + $isVarnish = $this->config->getType() == Config::VARNISH; if ($isVarnish && $isEsiBlock) { continue; } - // phpcs:ignore $tags[] = $block->getIdentities(); } } From 54270993b4dd2301113144441a27adb6ac80309b Mon Sep 17 00:00:00 2001 From: Chris Pook <chris.pook@absolutecommerce.co.uk> Date: Tue, 14 Jan 2020 09:51:37 +0000 Subject: [PATCH 153/666] 26375 Remove PrototypeJS dependency causing address issue This may need additional refactoring if PrototypeJS is being used (this is not currently clear) --- .../view/frontend/web/js/view/payment/method-renderer/cc-form.js | 1 - 1 file changed, 1 deletion(-) 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 5f06d26e2acfc..afe22475981ec 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 @@ -18,7 +18,6 @@ define( 'Magento_Vault/js/view/payment/vault-enabler', 'Magento_Braintree/js/view/payment/kount', 'mage/translate', - 'prototype', 'domReady!' ], function ( From daec86e617f04a317a7f00113c38e3d13f80fa37 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 14 Jan 2020 12:39:00 +0200 Subject: [PATCH 154/666] MC-30409: [FT] [MFTF] [2.4] Fix flaky test AdminCreateDuplicateProductTest (MC-14714) --- .../Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml | 1 + .../Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml index 4507e1f880a86..3eb617d19d54c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml @@ -22,6 +22,7 @@ <createData entity="Two_nested_categories" stepKey="subCategory"> <requiredEntity createDataKey="category"/> </createData> + <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="enableGenerateUrlRewrite"/> <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml index a3d3b897ef75d..9fcca06df5c69 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml @@ -42,7 +42,7 @@ <deleteData createDataKey="simpleSubCategory2" stepKey="deleteSimpleSubCategory2"/> <deleteData createDataKey="simpleSubCategory1" stepKey="deleteSimpleSubCategory1"/> <comment userInput="Disable config to generate category/product URL Rewrites " stepKey="commentDisableConfig" /> - <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 0" stepKey="disableGenerateUrlRewrite"/> + <magentoCLI command="config:set catalog/seo/generate_category_product_rewrites 1" stepKey="disableGenerateUrlRewrite"/> <amOnPage url="{{AdminLogoutPage.url}}" stepKey="amOnLogoutPage"/> </after> From bf580e444c1da52f09bdde5932e914800a7a4721 Mon Sep 17 00:00:00 2001 From: akartavtsev <akartavcev@magecom.net> Date: Tue, 14 Jan 2020 13:01:37 +0200 Subject: [PATCH 155/666] #25300 Mobile view issue on category page - Sort By label overlaps with Shop By button --- .../web/css/source/module/_toolbar.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less index b587c169f67eb..9d30f787a7431 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/module/_toolbar.less @@ -243,3 +243,13 @@ } } } + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { + .sorter-options { + margin: 0 2px; + } +} From b3982062f89f247abd5ee784e160f734c3e86a16 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Tue, 14 Jan 2020 16:18:24 +0200 Subject: [PATCH 156/666] Cover changes with jasmine tests --- .../frontend/web/js/add-to-wishlist.test.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.test.js index 207d14bf990c3..f157ae27ee532 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.test.js @@ -6,15 +6,22 @@ define([ 'jquery', 'Magento_Wishlist/js/add-to-wishlist' -], function ($) { +], function ($, Widget) { 'use strict'; describe('Testing addToWishlist widget', function () { - var wdContainer; + var wdContainer, + wishlistWidget, + eventMock = { + preventDefault: jasmine.createSpy(), + stopPropagation: jasmine.createSpy() + }; beforeEach(function () { wdContainer = $('<input type="hidden" class="bundle-option-11 product bundle option" \n' + 'name="bundle_option[11]" value="15" aria-required="true"/>'); + wishlistWidget = new Widget(); + $.fn.validation = {}; }); afterEach(function () { @@ -31,5 +38,15 @@ define([ }); expect(wdContainer.addToWishlist('option', 'bundleInfo')).toBe('test'); }); + + it('verify update wichlist with validate product qty, valid qty', function () { + var validation = spyOn($.fn, 'validation').and.returnValue(false); + + wishlistWidget._validateWishlistQty(eventMock); + expect(validation).toHaveBeenCalled(); + expect(eventMock.preventDefault).toHaveBeenCalled(); + expect(eventMock.stopPropagation).toHaveBeenCalled(); + }); + }); }); From c3b8a564ac259c141b29d6129cfe7008fd6b3ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Tue, 14 Jan 2020 17:42:47 +0100 Subject: [PATCH 157/666] Fix PHPUnit fatal error related with class methods not implemented --- .../Test/Unit/Plugin/DisableMultishippingModeTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php index 02ae1a70ce801..25a095381333e 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php @@ -59,10 +59,10 @@ protected function setUp() public function testExecuteTurnsOffMultishippingModeOnMultishippingQuote(): void { $subject = $this->createMock(Index::class); - $extensionAttributes = $this->createPartialMock( - CartExtensionInterface::class, - ['setShippingAssignments', 'getShippingAssignments'] - ); + $extensionAttributes = $this->getMockBuilder(CartExtensionInterface::class) + ->disableOriginalConstructor() + ->setMethods(['setShippingAssignments', 'getShippingAssignments']) + ->getMockForAbstractClass(); $extensionAttributes->method('getShippingAssignments') ->willReturn( $this->createMock(ShippingAssignmentInterface::class) From 4dcf4366112eda56257dcb7a736986aee17d5693 Mon Sep 17 00:00:00 2001 From: Daniel Renaud <drenaud@magento.com> Date: Tue, 14 Jan 2020 13:54:45 -0600 Subject: [PATCH 158/666] MC-23303: [Forwardport] Support preview for staged data --- .../Product/SearchCriteriaBuilder.php | 13 +- .../Model/Resolver/Category/Products.php | 58 ++----- .../Model/Resolver/Product/PriceRange.php | 4 +- .../Model/Resolver/Products.php | 40 +---- .../Model/Resolver/Products/Query/Filter.php | 151 +++++++++++++++--- .../Products/Query/ProductQueryInterface.php | 25 +++ .../Model/Resolver/Products/Query/Search.php | 43 ++++- .../FilterProcessor/CategoryFilter.php | 23 ++- app/code/Magento/CatalogGraphQl/etc/di.xml | 2 + app/code/Magento/GraphQl/etc/graphql/di.xml | 1 + .../Magento/Catalog/_files/categories.php | 3 +- .../_files/rule_by_category_ids_rollback.php | 27 ++++ .../Test/Legacy/ModuleDBChangeTest.php | 15 -- 13 files changed, 264 insertions(+), 141 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/ProductQueryInterface.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_category_ids_rollback.php diff --git a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php index 0e92bbbab4259..53d3b624285e9 100644 --- a/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php +++ b/app/code/Magento/CatalogGraphQl/DataProvider/Product/SearchCriteriaBuilder.php @@ -129,7 +129,7 @@ private function addVisibilityFilter(SearchCriteriaInterface $searchCriteria, bo ? $this->visibility->getVisibleInSearchIds() : $this->visibility->getVisibleInCatalogIds(); - $this->addFilter($searchCriteria, 'visibility', $visibilityIds); + $this->addFilter($searchCriteria, 'visibility', $visibilityIds, 'in'); } /** @@ -155,13 +155,20 @@ private function preparePriceAggregation(SearchCriteriaInterface $searchCriteria * @param SearchCriteriaInterface $searchCriteria * @param string $field * @param mixed $value + * @param string|null $condition */ - private function addFilter(SearchCriteriaInterface $searchCriteria, string $field, $value): void - { + private function addFilter( + SearchCriteriaInterface $searchCriteria, + string $field, + $value, + ?string $condition = null + ): void { $filter = $this->filterBuilder ->setField($field) ->setValue($value) + ->setConditionType($condition) ->create(); + $this->filterGroupBuilder->addFilter($filter); $filterGroups = $searchCriteria->getFilterGroups(); $filterGroups[] = $this->filterGroupBuilder->create(); diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Products.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Products.php index abc5ae7e1da7f..85b86f313de4d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Products.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Products.php @@ -7,16 +7,12 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category; -use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder; -use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search; -use Magento\Framework\App\ObjectManager; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\GraphQl\Query\Resolver\Argument\SearchCriteria\Builder; -use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Filter; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\CatalogGraphQl\Model\Resolver\Products\Query\ProductQueryInterface; /** * Category products resolver, used by GraphQL endpoints to retrieve products assigned to a category @@ -24,24 +20,7 @@ class Products implements ResolverInterface { /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface - */ - private $productRepository; - - /** - * @var Builder - * @deprecated - */ - private $searchCriteriaBuilder; - - /** - * @var Filter - * @deprecated - */ - private $filterQuery; - - /** - * @var Search + * @var ProductQueryInterface */ private $searchQuery; @@ -51,25 +30,15 @@ class Products implements ResolverInterface private $searchApiCriteriaBuilder; /** - * @param ProductRepositoryInterface $productRepository - * @param Builder $searchCriteriaBuilder - * @param Filter $filterQuery - * @param Search $searchQuery + * @param ProductQueryInterface $searchQuery * @param SearchCriteriaBuilder $searchApiCriteriaBuilder */ public function __construct( - ProductRepositoryInterface $productRepository, - Builder $searchCriteriaBuilder, - Filter $filterQuery, - Search $searchQuery = null, - SearchCriteriaBuilder $searchApiCriteriaBuilder = null + ProductQueryInterface $searchQuery, + SearchCriteriaBuilder $searchApiCriteriaBuilder ) { - $this->productRepository = $productRepository; - $this->searchCriteriaBuilder = $searchCriteriaBuilder; - $this->filterQuery = $filterQuery; - $this->searchQuery = $searchQuery ?? ObjectManager::getInstance()->get(Search::class); - $this->searchApiCriteriaBuilder = $searchApiCriteriaBuilder ?? - ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); + $this->searchQuery = $searchQuery; + $this->searchApiCriteriaBuilder = $searchApiCriteriaBuilder; } /** @@ -94,18 +63,17 @@ public function resolve( 'eq' => $value['id'] ] ]; - $searchCriteria = $this->searchApiCriteriaBuilder->build($args, false); - $searchResult = $this->searchQuery->getResult($searchCriteria, $info); + $searchResult = $this->searchQuery->getResult($args, $info); //possible division by 0 - if ($searchCriteria->getPageSize()) { - $maxPages = ceil($searchResult->getTotalCount() / $searchCriteria->getPageSize()); + if ($searchResult->getPageSize()) { + $maxPages = ceil($searchResult->getTotalCount() / $searchResult->getPageSize()); } else { $maxPages = 0; } - $currentPage = $searchCriteria->getCurrentPage(); - if ($searchCriteria->getCurrentPage() > $maxPages && $searchResult->getTotalCount() > 0) { + $currentPage = $searchResult->getCurrentPage(); + if ($searchResult->getCurrentPage() > $maxPages && $searchResult->getTotalCount() > 0) { $currentPage = new GraphQlInputException( __( 'currentPage value %1 specified is greater than the number of pages available.', @@ -118,7 +86,7 @@ public function resolve( 'total_count' => $searchResult->getTotalCount(), 'items' => $searchResult->getProductsSearchResult(), 'page_info' => [ - 'page_size' => $searchCriteria->getPageSize(), + 'page_size' => $searchResult->getPageSize(), 'current_page' => $currentPage, 'total_pages' => $maxPages ] diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/PriceRange.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/PriceRange.php index 9396b1f02b975..dbb52f2010930 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/PriceRange.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/PriceRange.php @@ -86,7 +86,7 @@ private function getMinimumProductPrice(SaleableInterface $product, StoreInterfa $priceProvider = $this->priceProviderPool->getProviderByProductType($product->getTypeId()); $regularPrice = $priceProvider->getMinimalRegularPrice($product)->getValue(); $finalPrice = $priceProvider->getMinimalFinalPrice($product)->getValue(); - $minPriceArray = $this->formatPrice($regularPrice, $finalPrice, $store); + $minPriceArray = $this->formatPrice((float) $regularPrice, (float) $finalPrice, $store); $minPriceArray['model'] = $product; return $minPriceArray; } @@ -103,7 +103,7 @@ private function getMaximumProductPrice(SaleableInterface $product, StoreInterfa $priceProvider = $this->priceProviderPool->getProviderByProductType($product->getTypeId()); $regularPrice = $priceProvider->getMaximalRegularPrice($product)->getValue(); $finalPrice = $priceProvider->getMaximalFinalPrice($product)->getValue(); - $maxPriceArray = $this->formatPrice($regularPrice, $finalPrice, $store); + $maxPriceArray = $this->formatPrice((float) $regularPrice, (float) $finalPrice, $store); $maxPriceArray['model'] = $product; return $maxPriceArray; } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products.php index 691f93e4148bc..e3d9ba2a9b3c6 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products.php @@ -7,6 +7,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver; +use Magento\CatalogGraphQl\Model\Resolver\Products\Query\ProductQueryInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Filter; use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search; @@ -24,51 +25,24 @@ class Products implements ResolverInterface { /** - * @var Builder - * @deprecated - */ - private $searchCriteriaBuilder; - - /** - * @var Search + * @var ProductQueryInterface */ private $searchQuery; - /** - * @var Filter - * @deprecated - */ - private $filterQuery; - - /** - * @var SearchFilter - * @deprecated - */ - private $searchFilter; - /** * @var SearchCriteriaBuilder */ private $searchApiCriteriaBuilder; /** - * @param Builder $searchCriteriaBuilder - * @param Search $searchQuery - * @param Filter $filterQuery - * @param SearchFilter $searchFilter + * @param ProductQueryInterface $searchQuery * @param SearchCriteriaBuilder|null $searchApiCriteriaBuilder */ public function __construct( - Builder $searchCriteriaBuilder, - Search $searchQuery, - Filter $filterQuery, - SearchFilter $searchFilter, + ProductQueryInterface $searchQuery, SearchCriteriaBuilder $searchApiCriteriaBuilder = null ) { - $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->searchQuery = $searchQuery; - $this->filterQuery = $filterQuery; - $this->searchFilter = $searchFilter; $this->searchApiCriteriaBuilder = $searchApiCriteriaBuilder ?? \Magento\Framework\App\ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); } @@ -95,11 +69,7 @@ public function resolve( ); } - //get product children fields queried - $productFields = (array)$info->getFieldSelection(1); - $includeAggregations = isset($productFields['filters']) || isset($productFields['aggregations']); - $searchCriteria = $this->searchApiCriteriaBuilder->build($args, $includeAggregations); - $searchResult = $this->searchQuery->getResult($searchCriteria, $info, $args); + $searchResult = $this->searchQuery->getResult($args, $info); if ($searchResult->getCurrentPage() > $searchResult->getTotalPages() && $searchResult->getTotalCount() > 0) { throw new GraphQlInputException( diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Filter.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Filter.php index cc25af44fdfbe..670eee9c4583e 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Filter.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Filter.php @@ -7,16 +7,23 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Products\Query; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\Catalog\Model\Layer\Resolver as LayerResolver; +use Magento\Catalog\Model\Product; use Magento\Framework\Api\SearchCriteriaInterface; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product; +use Magento\Framework\Exception\InputException; +use Magento\Framework\GraphQl\Query\Resolver\Argument\SearchCriteria\Builder as SearchCriteriaBuilder; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product as ProductProvider; use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResult; use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory; +use Magento\Search\Model\Query; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; /** * Retrieve filtered product data based off given search criteria in a format that GraphQL can interpret. */ -class Filter +class Filter implements ProductQueryInterface { /** * @var SearchResultFactory @@ -24,12 +31,12 @@ class Filter private $searchResultFactory; /** - * @var \Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product + * @var ProductProvider */ private $productDataProvider; /** - * @var \Magento\Catalog\Model\Layer\Resolver + * @var LayerResolver */ private $layerResolver; @@ -38,50 +45,154 @@ class Filter */ private $fieldSelection; + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + /** * @param SearchResultFactory $searchResultFactory - * @param Product $productDataProvider - * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver + * @param ProductProvider $productDataProvider + * @param LayerResolver $layerResolver * @param FieldSelection $fieldSelection + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param ScopeConfigInterface $scopeConfig */ public function __construct( SearchResultFactory $searchResultFactory, - Product $productDataProvider, - \Magento\Catalog\Model\Layer\Resolver $layerResolver, - FieldSelection $fieldSelection + ProductProvider $productDataProvider, + LayerResolver $layerResolver, + FieldSelection $fieldSelection, + SearchCriteriaBuilder $searchCriteriaBuilder, + ScopeConfigInterface $scopeConfig ) { $this->searchResultFactory = $searchResultFactory; $this->productDataProvider = $productDataProvider; $this->layerResolver = $layerResolver; $this->fieldSelection = $fieldSelection; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->scopeConfig = $scopeConfig; } /** * Filter catalog product data based off given search criteria * - * @param SearchCriteriaInterface $searchCriteria + * @param array $args * @param ResolveInfo $info - * @param bool $isSearch * @return SearchResult */ public function getResult( - SearchCriteriaInterface $searchCriteria, - ResolveInfo $info, - bool $isSearch = false + array $args, + ResolveInfo $info ): SearchResult { $fields = $this->fieldSelection->getProductsFieldSelection($info); - $products = $this->productDataProvider->getList($searchCriteria, $fields, $isSearch); + try { + $searchCriteria = $this->buildSearchCriteria($args, $info); + $searchResults = $this->productDataProvider->getList($searchCriteria, $fields); + } catch (InputException $e) { + return $this->createEmptyResult($args); + } + $productArray = []; - /** @var \Magento\Catalog\Model\Product $product */ - foreach ($products->getItems() as $product) { + /** @var Product $product */ + foreach ($searchResults->getItems() as $product) { $productArray[$product->getId()] = $product->getData(); $productArray[$product->getId()]['model'] = $product; } + //possible division by 0 + if ($searchCriteria->getPageSize()) { + $maxPages = (int)ceil($searchResults->getTotalCount() / $searchCriteria->getPageSize()); + } else { + $maxPages = 0; + } + + return $this->searchResultFactory->create( + [ + 'totalCount' => $searchResults->getTotalCount(), + 'productsSearchResult' => $productArray, + 'pageSize' => $searchCriteria->getPageSize(), + 'currentPage' => $searchCriteria->getCurrentPage(), + 'totalPages' => $maxPages, + ] + ); + } + + /** + * Build search criteria from query input args + * + * @param array $args + * @param ResolveInfo $info + * @return SearchCriteriaInterface + */ + private function buildSearchCriteria(array $args, ResolveInfo $info): SearchCriteriaInterface + { + if (!empty($args['filter'])) { + $args['filter'] = $this->formatFilters($args['filter']); + } + + $criteria = $this->searchCriteriaBuilder->build($info->fieldName, $args); + $criteria->setCurrentPage($args['currentPage']); + $criteria->setPageSize($args['pageSize']); + + return $criteria; + } + + /** + * Reformat filters + * + * @param array $filters + * @return array + * @throws InputException + */ + private function formatFilters(array $filters): array + { + $formattedFilters = []; + $minimumQueryLength = $this->scopeConfig->getValue( + Query::XML_PATH_MIN_QUERY_LENGTH, + ScopeInterface::SCOPE_STORE + ); + + foreach ($filters as $field => $filter) { + foreach ($filter as $condition => $value) { + if ($condition === 'match') { + // reformat 'match' filter so MySQL filtering behaves like SearchAPI filtering + $condition = 'like'; + $value = str_replace('%', '', trim($value)); + if (strlen($value) < $minimumQueryLength) { + throw new InputException(__('Invalid match filter')); + } + $value = '%' . preg_replace('/ +/', '%', $value) . '%'; + } + $formattedFilters[$field] = [$condition => $value]; + } + } + + return $formattedFilters; + } + + /** + * Return and empty SearchResult object + * + * Used for handling exceptions gracefully + * + * @param array $args + * @return SearchResult + */ + private function createEmptyResult(array $args): SearchResult + { return $this->searchResultFactory->create( [ - 'totalCount' => $products->getTotalCount(), - 'productsSearchResult' => $productArray + 'totalCount' => 0, + 'productsSearchResult' => [], + 'pageSize' => $args['pageSize'], + 'currentPage' => $args['currentPage'], + 'totalPages' => 0, ] ); } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/ProductQueryInterface.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/ProductQueryInterface.php new file mode 100644 index 0000000000000..580af5d87be26 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/ProductQueryInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogGraphQl\Model\Resolver\Products\Query; + +use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResult; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; + +/** + * Search for products by criteria + */ +interface ProductQueryInterface +{ + /** + * Get product search result + * + * @param array $args + * @param ResolveInfo $info + * @return SearchResult + */ + public function getResult(array $args, ResolveInfo $info): SearchResult; +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php index ef83cc6132ecc..8377cd9baa5b4 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php @@ -7,6 +7,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Products\Query; +use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder; use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\Api\Search\SearchCriteriaInterface; @@ -14,11 +15,12 @@ use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory; use Magento\Search\Api\SearchInterface; use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory; +use Magento\Search\Model\Search\PageSizeProvider; /** * Full text search for catalog using given search criteria. */ -class Search +class Search implements ProductQueryInterface { /** * @var SearchInterface @@ -31,7 +33,7 @@ class Search private $searchResultFactory; /** - * @var \Magento\Search\Model\Search\PageSizeProvider + * @var PageSizeProvider */ private $pageSizeProvider; @@ -50,21 +52,28 @@ class Search */ private $productsProvider; + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + /** * @param SearchInterface $search * @param SearchResultFactory $searchResultFactory - * @param \Magento\Search\Model\Search\PageSizeProvider $pageSize + * @param PageSizeProvider $pageSize * @param SearchCriteriaInterfaceFactory $searchCriteriaFactory * @param FieldSelection $fieldSelection * @param ProductSearch $productsProvider + * @param SearchCriteriaBuilder $searchCriteriaBuilder */ public function __construct( SearchInterface $search, SearchResultFactory $searchResultFactory, - \Magento\Search\Model\Search\PageSizeProvider $pageSize, + PageSizeProvider $pageSize, SearchCriteriaInterfaceFactory $searchCriteriaFactory, FieldSelection $fieldSelection, - ProductSearch $productsProvider + ProductSearch $productsProvider, + SearchCriteriaBuilder $searchCriteriaBuilder ) { $this->search = $search; $this->searchResultFactory = $searchResultFactory; @@ -72,21 +81,23 @@ public function __construct( $this->searchCriteriaFactory = $searchCriteriaFactory; $this->fieldSelection = $fieldSelection; $this->productsProvider = $productsProvider; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; } /** - * Return results of full text catalog search of given term, and will return filtered results if filter is specified + * Return product search results using Search API * - * @param SearchCriteriaInterface $searchCriteria + * @param array $args * @param ResolveInfo $info * @return SearchResult * @throws \Exception */ public function getResult( - SearchCriteriaInterface $searchCriteria, + array $args, ResolveInfo $info ): SearchResult { $queryFields = $this->fieldSelection->getProductsFieldSelection($info); + $searchCriteria = $this->buildSearchCriteria($args, $info); $realPageSize = $searchCriteria->getPageSize(); $realCurrentPage = $searchCriteria->getCurrentPage(); @@ -131,4 +142,20 @@ public function getResult( ] ); } + + /** + * Build search criteria from query input args + * + * @param array $args + * @param ResolveInfo $info + * @return SearchCriteriaInterface + */ + private function buildSearchCriteria(array $args, ResolveInfo $info): SearchCriteriaInterface + { + $productFields = (array)$info->getFieldSelection(1); + $includeAggregations = isset($productFields['filters']) || isset($productFields['aggregations']); + $searchCriteria = $this->searchCriteriaBuilder->build($args, $includeAggregations); + + return $searchCriteria; + } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php index e3b3588166163..92888a2775e17 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php @@ -9,11 +9,9 @@ use Magento\Catalog\Model\CategoryFactory; use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; -use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Framework\Api\Filter; use Magento\Framework\Api\SearchCriteria\CollectionProcessor\FilterProcessor\CustomFilterInterface; use Magento\Framework\Data\Collection\AbstractDb; -use Magento\Framework\Exception\LocalizedException; /** * Category filter allows to filter products collection using 'category_id' filter from search criteria. @@ -50,22 +48,23 @@ public function __construct( * @param Filter $filter * @param AbstractDb $collection * @return bool Whether the filter is applied - * @throws LocalizedException */ public function apply(Filter $filter, AbstractDb $collection) { - $conditionType = $filter->getConditionType(); - - if ($conditionType !== 'eq') { - throw new LocalizedException(__("'category_id' only supports 'eq' condition type.")); + $categoryIds = $filter->getValue(); + if (!is_array($categoryIds)) { + $categoryIds = [$categoryIds]; } - $categoryId = $filter->getValue(); - /** @var Collection $collection */ - $category = $this->categoryFactory->create(); - $this->categoryResourceModel->load($category, $categoryId); - $collection->addCategoryFilter($category); + $categoryProducts = []; + foreach ($categoryIds as $categoryId) { + $category = $this->categoryFactory->create(); + $this->categoryResourceModel->load($category, $categoryId); + $categoryProducts[$categoryId] = $category->getProductCollection()->getAllIds(); + } + $categoryProductIds = array_unique(array_merge(...$categoryProducts)); + $collection->addIdFilter($categoryProductIds); return true; } } diff --git a/app/code/Magento/CatalogGraphQl/etc/di.xml b/app/code/Magento/CatalogGraphQl/etc/di.xml index 1fe62fc442ecf..d6f75259e30d7 100644 --- a/app/code/Magento/CatalogGraphQl/etc/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/di.xml @@ -71,4 +71,6 @@ </type> <preference type="\Magento\CatalogGraphQl\Model\Resolver\Product\Price\Provider" for="\Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderInterface"/> + + <preference type="Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search" for="Magento\CatalogGraphQl\Model\Resolver\Products\Query\ProductQueryInterface"/> </config> diff --git a/app/code/Magento/GraphQl/etc/graphql/di.xml b/app/code/Magento/GraphQl/etc/graphql/di.xml index 03bae5c80e12c..2bcd44e9ae410 100644 --- a/app/code/Magento/GraphQl/etc/graphql/di.xml +++ b/app/code/Magento/GraphQl/etc/graphql/di.xml @@ -7,6 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Framework\App\FrontControllerInterface" type="Magento\GraphQl\Controller\GraphQl" /> + <preference for="Magento\Framework\Authorization\RoleLocatorInterface" type="Magento\Webapi\Model\WebapiRoleLocator" /> <type name="Magento\Authorization\Model\CompositeUserContext"> <arguments> <argument name="userContexts" xsi:type="array"> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php index 25bb55ffbc32c..4255d7d3c98e5 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/categories.php @@ -20,7 +20,7 @@ ] ); -/** @var Magento\Catalog\Api\CategoryLinkManagementInterface $linkManagement */ +/** @var Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement */ $categoryLinkManagement = $objectManager->create(\Magento\Catalog\Api\CategoryLinkManagementInterface::class); $reflectionClass = new \ReflectionClass(get_class($categoryLinkManagement)); $properties = [ @@ -115,6 +115,7 @@ ->setName('Inactive') ->setParentId(2) ->setPath('1/2/8') + ->setLevel(2) ->setAvailableSortBy('name') ->setDefaultSortBy('name') ->setIsActive(false) diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_category_ids_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_category_ids_rollback.php new file mode 100644 index 0000000000000..67584a300eacd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_category_ids_rollback.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\CatalogRule\Model\ResourceModel\Rule $catalogRuleResource */ +$catalogRuleResource = $objectManager->create(\Magento\CatalogRule\Model\ResourceModel\Rule::class); + +//Retrieve rule id by name +$select = $catalogRuleResource->getConnection()->select(); +$select->from($catalogRuleResource->getMainTable(), 'rule_id'); +$select->where('name = ?', 'test_category_rule'); +$ruleId = $catalogRuleResource->getConnection()->fetchOne($select); + +try { + /** @var \Magento\CatalogRule\Api\CatalogRuleRepositoryInterface $ruleRepository */ + $ruleRepository = $objectManager->create(\Magento\CatalogRule\Api\CatalogRuleRepositoryInterface::class); + $ruleRepository->deleteById($ruleId); +} catch (\Exception $ex) { + //Nothing to remove +} +/** @var \Magento\CatalogRule\Model\Indexer\IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(\Magento\CatalogRule\Model\Indexer\IndexBuilder::class); +$indexBuilder->reindexFull(); diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php index 876944e0027b4..15b3dc0e0a899 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php @@ -64,21 +64,6 @@ public static function setUpBeforeClass() } } - /** - * Test changes for module.xml files - */ - public function testModuleXmlFiles() - { - if (!self::$actualBranch) { - preg_match_all('|etc/module\.xml$|mi', self::$changedFileList, $matches); - $this->assertEmpty( - reset($matches), - 'module.xml changes for patch releases in non-actual branches are not allowed:' . PHP_EOL . - implode(PHP_EOL, array_values(reset($matches))) - ); - } - } - /** * Test changes for files in Module Setup dir */ From 7fd55602752d6d857874bac7bef54ea2c5adaa8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Tue, 14 Jan 2020 23:41:03 +0100 Subject: [PATCH 159/666] Add missing Annotations to MFTF tests --- .../Backend/Test/Mftf/Test/AdminLoginTest.xml | 2 +- .../AdminCardinalCommerceSettingsHiddenTest.xml | 1 + ...uctAttributeWithoutValueInCompareListTest.xml | 16 ++++++++-------- ...ontCategoryAccessibleWhenSuffixIsNullTest.xml | 1 + .../Test/AdminCMSPageCreateDisabledPageTest.xml | 1 + ...AdminCMSPageCreatePageForDefaultStoreTest.xml | 1 + ...minCMSPageCreatePageInSingleStoreModeTest.xml | 1 + .../Mftf/Test/AdminCMSPageCreatePageTest.xml | 3 ++- .../Test/AdminCMSPageCreatePageWithBlockTest.xml | 1 + .../Mftf/Test/NoErrorForMiniCartItemEditTest.xml | 1 + .../AdminScheduledImportSettingsHiddenTest.xml | 7 ++++--- ...NoJavascriptErrorOnAddYourReviewClickTest.xml | 1 + .../AdminCreateOrderWithDateTimeOptionUITest.xml | 1 + ...nSignifydConfigDependentOnActiveFieldTest.xml | 1 + .../AdminSetUpWatermarkForSwatchImageTest.xml | 1 + 15 files changed, 26 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml index ce33f01c60141..960e77db7194f 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginTest.xml @@ -24,4 +24,4 @@ <seeInCurrentUrl url="{{AdminLoginPage.url}}" stepKey="seeAdminLoginUrl"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml b/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml index a41b96f0db6e4..c891a578cdcca 100644 --- a/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml +++ b/app/code/Magento/CardinalCommerce/Test/Mftf/Test/AdminCardinalCommerceSettingsHiddenTest.xml @@ -9,6 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCardinalCommerceSettingsHiddenTest"> <annotations> + <stories value="Cardinal Commerce Settings"/> <features value="CardinalCommerce"/> <title value="CardinalCommerce settings hidden" /> <description value="CardinalCommerce config shouldn't be visible if the 3D secure is disabled for Authorize.Net."/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml index 70d2fb63941c7..c75abdbe43e24 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAttributeWithoutValueInCompareListTest.xml @@ -7,13 +7,13 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ProductAttributeWithoutValueInCompareListTest"> <annotations> <features value="Catalog"/> + <stories value="Product Comparison"/> <title value="Product attribute without value in compare list test"/> - <description - value="The product attribute that has no value should output 'N/A' on the product comparison page."/> + <description value="The product attribute that has no value should output 'N/A' on the product comparison page."/> <severity value="MINOR"/> <group value="Catalog"/> </annotations> @@ -22,7 +22,7 @@ <createData entity="textProductAttribute" stepKey="createProductAttribute"/> <createData entity="CatalogAttributeSet" stepKey="createAttributeSet"/> <amOnPage url="{{AdminProductAttributeSetEditPage.url}}/$$createAttributeSet.attribute_set_id$$/" - stepKey="onAttributeSetEdit"/> + stepKey="onAttributeSetEdit"/> <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignAttributeToGroup"> <argument name="group" value="Product Details"/> <argument name="attribute" value="$$createProductAttribute.attribute_code$$"/> @@ -69,11 +69,11 @@ </actionGroup> <!--See attribute default value in the comparison list--> <see userInput="$createProductAttribute.defaultValue$" - selector="{{StorefrontProductCompareMainSection.ProductAttributeByCodeAndProductName(ProductAttributeFrontendLabel.label, $createProductCustom.name$)}}" - stepKey="assertAttributeValueForProductCustom"/> + selector="{{StorefrontProductCompareMainSection.ProductAttributeByCodeAndProductName(ProductAttributeFrontendLabel.label, $createProductCustom.name$)}}" + stepKey="assertAttributeValueForProductCustom"/> <!--See N/A if attribute has no value in the comparison list--> <see userInput="N/A" - selector="{{StorefrontProductCompareMainSection.ProductAttributeByCodeAndProductName(ProductAttributeFrontendLabel.label, $createProductDefault.name$)}}" - stepKey="assertNAForProductDefault"/> + selector="{{StorefrontProductCompareMainSection.ProductAttributeByCodeAndProductName(ProductAttributeFrontendLabel.label, $createProductDefault.name$)}}" + stepKey="assertNAForProductDefault"/> </test> </tests> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml index ef8f2b6b1a3e2..6674c55064169 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Test/StorefrontCategoryAccessibleWhenSuffixIsNullTest.xml @@ -9,6 +9,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontCategoryAccessibleWhenSuffixIsNullTest"> <annotations> + <stories value="Url rewrites"/> <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"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml index 5b83807eca244..a5f43b090e9d6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreateDisabledPageTest.xml @@ -10,6 +10,7 @@ <test name="AdminCMSPageCreateDisabledPageTest"> <annotations> <features value="Cms"/> + <stories value="Create a CMS Page via the Admin"/> <title value="Create disabled CMS Page via the Admin"/> <description value="Admin should be able to create a CMS Page"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml index a9f5fcd8b17e0..d63952f7eb6c8 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageForDefaultStoreTest.xml @@ -10,6 +10,7 @@ <test name="AdminCMSPageCreatePageForDefaultStoreTest"> <annotations> <features value="Cms"/> + <stories value="Create a CMS Page via the Admin"/> <title value="Create CMS Page via the Admin for default store"/> <description value="Admin should be able to create a CMS Page"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml index 1ec85f90f46ef..d2124b5d83be6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageInSingleStoreModeTest.xml @@ -10,6 +10,7 @@ <test name="AdminCMSPageCreatePageInSingleStoreModeTest"> <annotations> <features value="Cms"/> + <stories value="Create a CMS Page via the Admin"/> <title value="Create CMS Page via the Admin in single store mode"/> <description value="Admin should be able to create a CMS Page"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml index 947fa92f2c8ff..d33d7484f7770 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageTest.xml @@ -6,10 +6,11 @@ */ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCMSPageCreatePageTest"> <annotations> <features value="Cms"/> + <stories value="Create a CMS Page via the Admin"/> <title value="Create CMS Page via the Admin"/> <description value="Admin should be able to create a CMS Page"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml index a6c67dc61dd97..1600a0d9d8d0f 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCMSPageCreatePageWithBlockTest.xml @@ -10,6 +10,7 @@ <test name="AdminCMSPageCreatePageWithBlockTest"> <annotations> <features value="Cms"/> + <stories value="Create a CMS Page via the Admin"/> <title value="Create CMS Page that contains block content via the Admin"/> <description value="Admin should be able to create a CMS Page"/> <severity value="CRITICAL"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml index 42bad3e4bb8bf..914550fabf39b 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoErrorForMiniCartItemEditTest.xml @@ -11,6 +11,7 @@ <test name="NoErrorForMiniCartItemEditTest"> <annotations> <features value="ConfigurableProduct"/> + <stories value="Storefront Minicart Update"/> <title value="No error for minicart item edit test"/> <description value="Already selected configurable option should be selected when configurable product is edited from minicart"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml b/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml index 0320b6f422cd6..853872dd907bd 100644 --- a/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml +++ b/app/code/Magento/Directory/Test/Mftf/Test/AdminScheduledImportSettingsHiddenTest.xml @@ -6,11 +6,12 @@ */ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminScheduledImportSettingsHiddenTest"> <annotations> <features value="Directory"/> - <title value="Scheduled import settings hidden" /> + <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'"/> <severity value="MINOR"/> </annotations> @@ -24,7 +25,7 @@ <magentoCLI command="config:set currency/import/enabled 0" stepKey="disableCurrencyImport"/> </after> - <amOnPage url="{{AdminCurrencySetupPage.url}}" stepKey="openCurrencyOptionsPage" /> + <amOnPage url="{{AdminCurrencySetupPage.url}}" stepKey="openCurrencyOptionsPage"/> <conditionalClick dependentSelector="{{AdminScheduledImportSettingsSection.enabled}}" visible="false" selector="{{AdminScheduledImportSettingsSection.head}}" stepKey="openCollapsibleBlock"/> <see selector="{{AdminScheduledImportSettingsSection.service}}" userInput="Fixer.io" stepKey="seeServiceFixerIo"/> <selectOption selector="{{AdminScheduledImportSettingsSection.enabled}}" userInput="0" stepKey="disableCurrencyImportOption"/> diff --git a/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml b/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml index 99e418a950c69..c981d70938e11 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/StorefrontNoJavascriptErrorOnAddYourReviewClickTest.xml @@ -11,6 +11,7 @@ <test name="StorefrontNoJavascriptErrorOnAddYourReviewClickTest"> <annotations> <features value="Review"/> + <stories value="Storefront Add Review"/> <title value="Storefront no javascript error on 'Add Your Review' click test"/> <description value="Verify no javascript error occurs when customer clicks 'Add Your Review' link"/> <severity value="MAJOR"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml index 7e58e55c8981e..1fa01e0efa156 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithDateTimeOptionUITest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCreateOrderWithDateTimeOptionUITest"> <annotations> + <stories value="Create Order"/> <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"/> diff --git a/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml b/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml index dcae0c4091ba6..b8fb91c4dcd99 100644 --- a/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml +++ b/app/code/Magento/Signifyd/Test/Mftf/Test/AdminSignifydConfigDependentOnActiveFieldTest.xml @@ -10,6 +10,7 @@ <test name="AdminSignifydConfigDependentOnActiveFieldTest"> <annotations> <features value="Signifyd"/> + <stories value="Signify ID Settings"/> <title value="Signifyd config dependent on active field" /> <description value="Signifyd system configs dependent by Enable this Solution field."/> <severity value="MINOR"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml index 569952019b29b..b24420061db65 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminSetUpWatermarkForSwatchImageTest.xml @@ -11,6 +11,7 @@ <test name="AdminSetUpWatermarkForSwatchImageTest"> <annotations> <features value="Swatches"/> + <stories value="Product Swatches Images"/> <title value="Possibility to set up watermark for a swatch image type"/> <description value="Possibility to set up watermark for a swatch image type"/> <severity value="MAJOR"/> From 4be4f15964bb0d06da218dfd2672ded9a9223f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Tue, 14 Jan 2020 23:50:43 +0100 Subject: [PATCH 160/666] Add missing severity to Test Cases --- .../Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml | 2 ++ .../Test/Mftf/Test/NewCustomerPasswordComplexityTest.xml | 1 + .../Security/Test/Mftf/Test/NewCustomerPasswordLengthTest.xml | 1 + .../AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml | 1 + .../Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml | 1 + .../Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml | 1 + .../AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml | 1 + .../Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml | 1 + ...AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml | 1 + 9 files changed, 10 insertions(+) diff --git a/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml b/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml index 6f46bbf99d218..966be94d9e404 100644 --- a/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml +++ b/app/code/Magento/Integration/Test/Mftf/Test/AdminDeleteIntegrationEntityTest.xml @@ -14,6 +14,8 @@ <stories value="System Integration"/> <title value="Admin system integration"/> <description value="Admin Deletes Created Integration"/> + <severity value="MAJOR"/> + <testCaseId value="MC-28027"/> <group value="integration"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordComplexityTest.xml b/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordComplexityTest.xml index 74a9c68cb2f79..d7151aff22fa7 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordComplexityTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordComplexityTest.xml @@ -15,6 +15,7 @@ <title value="Notify the customer if password complexity does not match the requirements"/> <description value="Notify the customer if password complexity does not match the requirements"/> <testCaseId value="MC-14368"/> + <severity value="CRITICAL"/> <group value="security"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordLengthTest.xml b/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordLengthTest.xml index a10059d0603c5..298b4de11f9ca 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordLengthTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/NewCustomerPasswordLengthTest.xml @@ -15,6 +15,7 @@ <title value="Notify the customer if password length does not match the requirements"/> <description value="Notify the customer if password length does not match the requirements"/> <testCaseId value="MC-14367"/> + <severity value="CRITICAL"/> <group value="security"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml index 4b9f37f628f34..ad952225c2ff5 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteHypenAsRequestPathTest.xml @@ -14,6 +14,7 @@ <title value="Delete category URL rewrite, hyphen as request path"/> <description value="Delete category URL rewrite, hyphen as request path"/> <testCaseId value="MC-5348" /> + <severity value="MAJOR"/> <group value="urlRewrite"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml index 7c4023c6d0f75..dc9928773bf35 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCategoryUrlRewriteWithRequestPathTest.xml @@ -14,6 +14,7 @@ <title value="Delete category URL rewrite, with request path"/> <description value="Delete category URL rewrite, with request path"/> <testCaseId value="MC-5349" /> + <severity value="MAJOR"/> <group value="urlRewrite"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml index c40dd3256114e..e2f0d6af0deab 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithNoRedirectsTest.xml @@ -13,6 +13,7 @@ <stories value="Delete CMS Page URL rewrite with No Redirects"/> <title value="Delete CMS Page URL rewrite with No Redirects"/> <description value="Log in to admin and delete CMS Page URL rewrite with No Redirects"/> + <severity value="CRITICAL"/> <testCaseId value="MC-14648"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml index 43de4123f35a8..e3d417f3c1f39 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminDeleteCmsPageUrlRewriteWithTemporaryRedirectTest.xml @@ -14,6 +14,7 @@ <title value="Delete CMS Page URL rewrite with Temporary Redirect"/> <description value="Log in to admin and delete CMS Page URL rewrite with Temporary Redirect"/> <testCaseId value="MC-14650"/> + <severity value="CRITICAL"/> <group value="mtf_migrated"/> </annotations> <before> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml index 6467a5051631d..b2fa13ead1164 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithNoRedirectTest.xml @@ -12,6 +12,7 @@ <stories value="Update CMS Page URL Redirect With No Redirect"/> <title value="Update CMS Page URL Redirect With No Redirect"/> <description value="Login as Admin and tried to update the created URL Rewrite for CMS page"/> + <severity value="MINOR"/> <group value="cMSContent"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml index a7cadcdf753c3..b00241bc3acac 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUpdateCmsPageRewriteEntityWithTemporaryRedirectTest.xml @@ -12,6 +12,7 @@ <stories value="Update CMS Page URL Redirect With Temporary Redirect"/> <title value="Update CMS Page URL Redirect With Temporary Redirect"/> <description value="Login as Admin and tried to update the created URL Rewrite for CMS page"/> + <severity value="MINOR"/> <group value="cMSContent"/> <group value="mtf_migrated"/> </annotations> From 4d814cba6ad8969a01e84113eacff03a1547c77e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 15 Jan 2020 13:49:18 +0200 Subject: [PATCH 161/666] MC-30409: [FT] [MFTF] [2.4] Fix flaky test AdminCreateDuplicateProductTest (MC-14714) --- .../Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml | 3 --- .../Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml | 3 --- 2 files changed, 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml index 472de07baccdd..3eb617d19d54c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDuplicateProductTest.xml @@ -15,9 +15,6 @@ <testCaseId value="MC-14714"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-30409"/> - </skip> </annotations> <before> diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml index 3f2ae13a16657..9fcca06df5c69 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminUrlRewritesForProductAfterImportTest.xml @@ -16,9 +16,6 @@ <severity value="MAJOR"/> <testCaseId value="MC-20229"/> <group value="urlRewrite"/> - <skip> - <issueId value="MC-30409"/> - </skip> </annotations> <before> <comment userInput="Set the configuration for Generate category/product URL Rewrites" stepKey="commentSetURLRewriteConfiguration" /> From 364b51a08021abd491e89f9ec838e78476420ab0 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 15 Jan 2020 06:15:24 -0600 Subject: [PATCH 162/666] Issue #26332 BeforeOrderPaymentSaveObserver override payment insructions --- .../BeforeOrderPaymentSaveObserver.php | 3 ++- .../BeforeOrderPaymentSaveObserverTest.php | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php b/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php index daf1cef3fff60..d7cad6b62e993 100644 --- a/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php +++ b/app/code/Magento/OfflinePayments/Observer/BeforeOrderPaymentSaveObserver.php @@ -30,7 +30,8 @@ public function execute(\Magento\Framework\Event\Observer $observer) Banktransfer::PAYMENT_METHOD_BANKTRANSFER_CODE, Cashondelivery::PAYMENT_METHOD_CASHONDELIVERY_CODE ]; - if (in_array($payment->getMethod(), $instructionMethods)) { + if (in_array($payment->getMethod(), $instructionMethods) + && empty($payment->getAdditionalInformation('instructions'))) { $payment->setAdditionalInformation( 'instructions', $payment->getMethodInstance()->getInstructions() diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php index 51edaea0e659c..0b482a805175a 100644 --- a/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php +++ b/app/code/Magento/OfflinePayments/Test/Unit/Observer/BeforeOrderPaymentSaveObserverTest.php @@ -172,4 +172,24 @@ public function testBeforeOrderPaymentSaveWithOthers() $this->_model->execute($this->observer); } + + /** + * @param string $methodCode + * @dataProvider dataProviderBeforeOrderPaymentSaveWithInstructions + */ + public function testBeforeOrderPaymentSaveWithInstructionsAlreadySet($methodCode) + { + $this->payment + ->method('getMethod') + ->willReturn($methodCode); + + $this->payment->expects(self::once()) + ->method('getAdditionalInformation') + ->willReturn('Test'); + + $this->payment->expects(self::never()) + ->method('setAdditionalInformation'); + + $this->_model->execute($this->observer); + } } From 4b9b6fa85fcbb2f47efe0f67ab5889b355b2f300 Mon Sep 17 00:00:00 2001 From: Daniel Ruf <d.ruf@bitexpert.de> Date: Wed, 15 Jan 2020 13:06:32 +0100 Subject: [PATCH 163/666] Apply review feedback --- app/code/Magento/Customer/ViewModel/Address.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/app/code/Magento/Customer/ViewModel/Address.php b/app/code/Magento/Customer/ViewModel/Address.php index a6bcbfcb40676..58df4c1adc1d4 100644 --- a/app/code/Magento/Customer/ViewModel/Address.php +++ b/app/code/Magento/Customer/ViewModel/Address.php @@ -11,25 +11,17 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\View\Element\Block\ArgumentInterface; -/** - * Customer address view model. - */ - /** - * Address view model + * Custom address view model */ class Address implements ArgumentInterface { /** - * Data helper - * * @var DataHelper */ private $helperData; /** - * Address helper - * * @var AddressHelper */ private $helperAddress; @@ -53,9 +45,7 @@ public function __construct( * Get string with frontend validation classes for attribute * * @param string $attributeCode - * * @return string - * * @throws \Magento\Framework\Exception\LocalizedException */ public function dataGetAttributeValidationClass($attributeCode) @@ -67,9 +57,7 @@ public function dataGetAttributeValidationClass($attributeCode) * Get string with frontend validation classes for attribute * * @param string $attributeCode - * * @return string - * * @throws \Magento\Framework\Exception\LocalizedException */ public function addressGetAttributeValidationClass($attributeCode) From 4192ff3af9039f50f6ac3d98f688dee743ffea2e Mon Sep 17 00:00:00 2001 From: Raul E Watson <raul.watson@maginus.com> Date: Thu, 16 Jan 2020 05:43:25 +0000 Subject: [PATCH 164/666] #895 Fix for Media Gallery buttons are shifted to the left --- .../view/adminhtml/web/css/source/_module.less | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less diff --git a/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less b/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less new file mode 100644 index 0000000000000..4abcfb702a3dd --- /dev/null +++ b/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less @@ -0,0 +1,13 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +.modal-slide { + .media-gallery-modal { + .page-main-actions { + .page-action-buttons{ + text-align: right; + } + } + } +} From 627ea42161550c38f246aa236a26dd292ac6a441 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Thu, 9 Jan 2020 16:58:23 +0200 Subject: [PATCH 165/666] =?UTF-8?q?magento/magento2#:=20Remove=20unused=20?= =?UTF-8?q?=E2=80=9CDefault=20Email=20Domain=E2=80=9D=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Magento/Customer/i18n/en_US.csv | 1 - app/code/Magento/Sales/Model/AdminOrder/Create.php | 8 -------- 2 files changed, 9 deletions(-) diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index a70aa08dba735..f1b82bd5a4395 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -432,7 +432,6 @@ Strong,Strong "Default Value for Disable Automatic Group Changes Based on VAT ID","Default Value for Disable Automatic Group Changes Based on VAT ID" "Show VAT Number on Storefront","Show VAT Number on Storefront" "To show VAT number on Storefront, set Show VAT Number on Storefront option to Yes.","To show VAT number on Storefront, set Show VAT Number on Storefront option to Yes." -"Default Email Domain","Default Email Domain" "Default Welcome Email","Default Welcome Email" "Email template chosen based on theme fallback when ""Default"" option is selected.","Email template chosen based on theme fallback when ""Default"" option is selected." "Default Welcome Email Without Password","Default Welcome Email Without Password" diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 7396118aa9fc0..81f918e455069 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -28,14 +28,6 @@ */ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\Model\Cart\CartInterface { - /** - * Path to "CUSTOMERS > Customer Configuration > Create New Account Options > Default Email Domain" setting - * - * @deprecated since version 2.2.6 - * @see \Magento\Sales\Model\AdminOrder\Create. Constant usage has been removed from _getNewCustomerEmail() method. - */ - const XML_PATH_DEFAULT_EMAIL_DOMAIN = 'customer/create_account/email_domain'; - /** * Quote session object * From b6a0f86313ceb261638c6d648e8624e0971f36a3 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Thu, 16 Jan 2020 11:13:20 +0200 Subject: [PATCH 166/666] MC-30111: [2.4] Test StorefrontCustomerCheckoutTest fails on Jenkins --- .../Test/StorefrontCustomerCheckoutTest.xml | 117 ++++++++---------- 1 file changed, 53 insertions(+), 64 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml index 861f379988031..8bdbabb584b83 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCustomerCheckoutTest.xml @@ -10,88 +10,77 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="StorefrontCustomerCheckoutTest"> <annotations> - <features value="Checkout"/> - <stories value="Checkout via the Admin"/> - <title value="Customer Checkout via the Admin"/> + <features value="Customer Checkout"/> + <stories value="Checkout via Storefront"/> + <title value="Customer Checkout via Storefront"/> <description value="Should be able to place an order as a customer."/> <severity value="CRITICAL"/> - <testCaseId value="MC-5922"/> + <testCaseId value="MC-30274"/> <group value="checkout"/> - <skip> - <issueId value="MC-30111"/> - </skip> </annotations> <before> - <createData entity="SimpleSubCategory" stepKey="simplecategory"/> - <createData entity="SimpleProduct" stepKey="simpleproduct1"> - <requiredEntity createDataKey="simplecategory"/> + <createData entity="SimpleSubCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="Simple_US_Customer" stepKey="simpleuscustomer"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> - <!--Clear filters--> - <amOnPage url="{{AdminCustomerPage.url}}" stepKey="navigateToCustomers"/> - <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingCustomerFilters"/> - - <actionGroup ref="logout" stepKey="logout"/> - <deleteData createDataKey="simpleproduct1" stepKey="deleteProduct1"/> - <deleteData createDataKey="simplecategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteSimpleCategory"/> + <deleteData createDataKey="createCustomer" stepKey="deleteUsCustomer"/> + <actionGroup ref="AdminClearCustomersFiltersActionGroup" stepKey="resetCustomerFilters"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> </after> - <actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin"> - <argument name="Customer" value="$$simpleuscustomer$$" /> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="storefrontCustomerLogin"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateToCategoryPage"> + <argument name="category" value="$$createCategory$$"/> </actionGroup> - <amOnPage url="{{StorefrontCategoryPage.url($$simplecategory.name$$)}}" stepKey="onCategoryPage"/> <waitForPageLoad stepKey="waitForCatalogPageLoad"/> - <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> - <click selector="{{StorefrontCategoryMainSection.AddToCartBtn}}" stepKey="addToCart"/> - <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" time="30" stepKey="waitForProductAdded"/> - <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $$simpleproduct1.name$$ to your shopping cart." stepKey="seeAddedToCartMessage"/> - <see selector="{{StorefrontMinicartSection.quantity}}" userInput="1" stepKey="seeCartQuantity"/> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart" /> - <click stepKey="s35" selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}"/> - <waitForElement stepKey="s36" selector="{{CheckoutShippingMethodsSection.next}}" time="30"/> - <click stepKey="s37" selector="{{CheckoutShippingMethodsSection.next}}" /> - <!-- Checkout select Check/Money Order payment --> - <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> - <waitForPageLoad stepKey="s39"/> - <waitForElement stepKey="s41" selector="{{CheckoutPaymentSection.placeOrder}}" time="30" /> - <see stepKey="s47" selector="{{CheckoutPaymentSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <click stepKey="s49" selector="{{CheckoutPaymentSection.placeOrder}}" /> - <waitForPageLoad stepKey="s51"/> - <grabTextFrom stepKey="s53" selector="{{CheckoutSuccessMainSection.orderNumber22}}"/> - <see stepKey="s55" selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" /> + <actionGroup ref="StorefrontAddCategoryProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="productCount" value="CONST.one"/> + </actionGroup> + + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + <actionGroup ref="CheckoutSelectFlatRateShippingMethodActionGroup" stepKey="selectFlatRate"/> + <actionGroup ref="StorefrontCheckoutForwardFromShippingStepActionGroup" stepKey="goToReview"/> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrder"/> + <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="clickOnPlaceOrder"> + <argument name="orderNumberMessage" value="CONST.successCheckoutOrderNumberMessage"/> + <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/> + </actionGroup> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="orderNumber"/> - <amOnPage stepKey="s67" url="{{AdminOrdersPage.url}}"/> - <waitForPageLoad stepKey="s75"/> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFiltersIfPresent"/> - <fillField stepKey="s77" selector="{{AdminOrdersGridSection.search}}" userInput="{$s53}" /> - <waitForPageLoad stepKey="s78"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <click stepKey="s81" selector="{{AdminOrdersGridSection.submitSearch22}}" /> - <waitForPageLoad stepKey="s831"/> - <click stepKey="s84" selector="{{AdminOrdersGridSection.firstRow}}" /> - <waitForPageLoad stepKey="waitForOrderToLoad"/> - <see stepKey="s85" selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" /> - <see stepKey="s87" selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="Customer" /> - <see stepKey="s89" selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="$$simpleuscustomer.email$$" /> - <see stepKey="s91" selector="{{AdminOrderDetailsInformationSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <see stepKey="s93" selector="{{AdminOrderDetailsInformationSection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}}" /> - <see stepKey="s95" selector="{{AdminOrderDetailsInformationSection.itemsOrdered}}" userInput="$$simpleproduct1.name$$" /> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="addFilterToGridAndOpenOrder"> + <argument name="orderId" value="{$orderNumber}"/> + </actionGroup> + + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="verifyOrderStatus"/> + <see selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="Customer" stepKey="verifyAccountInformation"/> + <see selector="{{AdminOrderDetailsInformationSection.accountInformation}}" userInput="$$createCustomer.email$$" stepKey="verifyCustomerEmail"/> + <see selector="{{AdminOrderDetailsInformationSection.billingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="verifyBillingAddress"/> + <see selector="{{AdminOrderDetailsInformationSection.shippingAddress}}" userInput="{{US_Address_TX.street[0]}}" stepKey="verifyShippingAddress"/> + <see selector="{{AdminOrderDetailsInformationSection.itemsOrdered}}" userInput="$$createSimpleProduct.name$$" stepKey="verifyProductName"/> + + <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="openCustomerEditPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> - <amOnPage stepKey="s96" url="{{AdminCustomerPage.url}}"/> - <waitForPageLoad stepKey="s97"/> - <waitForElementVisible selector="{{AdminCustomerFiltersSection.filtersButton}}" time="30" stepKey="waitFiltersButton"/> - <click stepKey="s98" selector="{{AdminCustomerFiltersSection.filtersButton}}"/> - <fillField stepKey="s99" selector="{{AdminCustomerFiltersSection.emailInput}}" userInput="$$simpleuscustomer.email$$"/> - <click stepKey="s100" selector="{{AdminCustomerFiltersSection.apply}}"/> - <click stepKey="s101" selector="{{AdminCustomerGridSection.firstRowEditLink}}"/> - <click stepKey="s102" selector="{{AdminEditCustomerInformationSection.orders}}"/> - <see stepKey="s103" selector="{{AdminEditCustomerOrdersSection.orderGrid}}" userInput="$$simpleuscustomer.firstname$$ $$simpleuscustomer.lastname$$" /> + <click selector="{{AdminEditCustomerInformationSection.orders}}" stepKey="navigateToOrdersTab"/> + <waitForElementVisible selector="{{AdminEditCustomerOrdersSection.orderGrid}}" stepKey="waitForOrdersGridVisible"/> + <see selector="{{AdminEditCustomerOrdersSection.orderGrid}}" userInput="$$createCustomer.firstname$$ $$createCustomer.lastname$$" stepKey="verifyOrder"/> </test> <test name="StorefrontCustomerCheckoutTestWithMultipleAddressesAndTaxRates"> <annotations> From a8f1ee7a56fcb13496b4ea70dd906c61d66685e9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Thu, 16 Jan 2020 11:58:02 +0200 Subject: [PATCH 167/666] magento/magento2#25488: Composer update. --- composer.lock | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index b6d834610059a..d00a2c337df68 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "8d8e6b87c1f6ac98b3b7331eba9473f3", + "content-hash": "8ca9b4a6ea63c83444b1506f53d6c115", "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", @@ -2841,6 +2841,7 @@ "captcha", "zf" ], + "abandoned": "laminas/laminas-captcha", "time": "2019-06-18T09:32:52+00:00" }, { @@ -2894,6 +2895,7 @@ "code", "zf" ], + "abandoned": "laminas/laminas-code", "time": "2019-08-31T14:14:34+00:00" }, { @@ -2950,6 +2952,7 @@ "config", "zf2" ], + "abandoned": "laminas/laminas-config", "time": "2016-02-04T23:01:10+00:00" }, { @@ -3003,6 +3006,7 @@ "console", "zf" ], + "abandoned": "laminas/laminas-console", "time": "2019-02-04T19:48:22+00:00" }, { @@ -3053,6 +3057,7 @@ "crypt", "zf2" ], + "abandoned": "laminas/laminas-crypt", "time": "2016-02-03T23:46:30+00:00" }, { @@ -3111,6 +3116,7 @@ "db", "zf" ], + "abandoned": "laminas/laminas-db", "time": "2019-02-25T11:37:45+00:00" }, { @@ -3158,6 +3164,7 @@ "di", "zf2" ], + "abandoned": "laminas/laminas-di", "time": "2016-04-25T20:58:11+00:00" }, { @@ -3220,6 +3227,7 @@ "psr", "psr-7" ], + "abandoned": "laminas/laminas-diactoros", "time": "2019-08-06T17:53:53+00:00" }, { @@ -3265,6 +3273,7 @@ "escaper", "zf" ], + "abandoned": "laminas/laminas-escaper", "time": "2019-09-05T20:03:20+00:00" }, { @@ -3319,6 +3328,7 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" }, { @@ -3382,6 +3392,7 @@ "feed", "zf" ], + "abandoned": "laminas/laminas-feed", "time": "2019-03-05T20:08:49+00:00" }, { @@ -3447,6 +3458,7 @@ "filter", "zf" ], + "abandoned": "laminas/laminas-filter", "time": "2019-08-19T07:08:04+00:00" }, { @@ -3525,6 +3537,7 @@ "form", "zf" ], + "abandoned": "laminas/laminas-form", "time": "2019-10-04T10:46:36+00:00" }, { @@ -3580,6 +3593,7 @@ "zend", "zf" ], + "abandoned": "laminas/laminas-http", "time": "2019-02-19T18:58:14+00:00" }, { @@ -3640,6 +3654,7 @@ "hydrator", "zf" ], + "abandoned": "laminas/laminas-hydrator", "time": "2019-10-04T11:17:36+00:00" }, { @@ -3708,6 +3723,7 @@ "i18n", "zf" ], + "abandoned": "laminas/laminas-i18n", "time": "2019-09-30T12:04:37+00:00" }, { @@ -3765,6 +3781,7 @@ "inputfilter", "zf" ], + "abandoned": "laminas/laminas-inputfilter", "time": "2019-08-28T19:45:32+00:00" }, { @@ -3820,6 +3837,7 @@ "json", "zf2" ], + "abandoned": "laminas/laminas-json", "time": "2016-02-04T21:20:26+00:00" }, { @@ -3865,6 +3883,7 @@ "loader", "zf" ], + "abandoned": "laminas/laminas-loader", "time": "2019-09-04T19:38:14+00:00" }, { @@ -3935,6 +3954,7 @@ "logging", "zf" ], + "abandoned": "laminas/laminas-log", "time": "2019-08-23T21:28:18+00:00" }, { @@ -3997,6 +4017,7 @@ "mail", "zf" ], + "abandoned": "laminas/laminas-mail", "time": "2018-06-07T13:37:07+00:00" }, { @@ -4047,6 +4068,7 @@ "math", "zf2" ], + "abandoned": "laminas/laminas-math", "time": "2018-12-04T15:34:17+00:00" }, { @@ -4097,6 +4119,7 @@ "mime", "zf" ], + "abandoned": "laminas/laminas-mime", "time": "2019-10-16T19:30:37+00:00" }, { @@ -4156,6 +4179,7 @@ "modulemanager", "zf" ], + "abandoned": "laminas/laminas-modulemanager", "time": "2019-10-28T13:29:38+00:00" }, { @@ -4251,6 +4275,7 @@ "mvc", "zf2" ], + "abandoned": "laminas/laminas-mvc", "time": "2018-05-03T13:13:41+00:00" }, { @@ -4300,6 +4325,7 @@ "psr", "psr-7" ], + "abandoned": "laminas/laminas-psr7bridge", "time": "2016-05-10T21:44:39+00:00" }, { @@ -4357,6 +4383,7 @@ "serializer", "zf" ], + "abandoned": "laminas/laminas-serializer", "time": "2019-10-19T08:06:30+00:00" }, { @@ -4404,6 +4431,7 @@ "server", "zf" ], + "abandoned": "laminas/laminas-server", "time": "2019-10-16T18:27:05+00:00" }, { @@ -4456,6 +4484,7 @@ "servicemanager", "zf2" ], + "abandoned": "laminas/laminas-servicemanager", "time": "2018-06-22T14:49:54+00:00" }, { @@ -4523,6 +4552,7 @@ "session", "zf" ], + "abandoned": "laminas/laminas-session", "time": "2019-10-28T19:40:43+00:00" }, { @@ -4576,6 +4606,7 @@ "soap", "zf2" ], + "abandoned": "laminas/laminas-soap", "time": "2019-04-30T16:45:35+00:00" }, { @@ -4622,6 +4653,7 @@ "stdlib", "zf" ], + "abandoned": "laminas/laminas-stdlib", "time": "2018-08-28T21:34:05+00:00" }, { @@ -4670,6 +4702,7 @@ "text", "zf" ], + "abandoned": "laminas/laminas-text", "time": "2019-10-16T20:36:27+00:00" }, { @@ -4717,6 +4750,7 @@ "uri", "zf" ], + "abandoned": "laminas/laminas-uri", "time": "2019-10-07T13:35:33+00:00" }, { @@ -4790,6 +4824,7 @@ "validator", "zf" ], + "abandoned": "laminas/laminas-validator", "time": "2019-10-29T08:33:25+00:00" }, { @@ -4877,6 +4912,7 @@ "view", "zf" ], + "abandoned": "laminas/laminas-view", "time": "2019-10-11T21:10:04+00:00" } ], From 1aed73ef7b48ea17e9f5f52d949dba056b591cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chitesh=40wagento=2Ecom=E2=80=9D?= <hitesh@wagento.com> Date: Thu, 16 Jan 2020 17:17:17 +0530 Subject: [PATCH 168/666] [Fixed Compare Products section not showing in mobile view under 767px] --- .../Magento/blank/Magento_Catalog/web/css/source/_module.less | 3 +-- .../Magento/luma/Magento_Catalog/web/css/source/_module.less | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) 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 44e93087399a1..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 @@ -544,8 +544,7 @@ .compare, .product-addto-links .action.tocompare, - .product-item-actions .actions-secondary > .action.tocompare, - [class*='block-compare'] { + .product-item-actions .actions-secondary > .action.tocompare { display: none; } } 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 27533a0eb598f..9a3bae98c0d9c 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 @@ -1007,8 +1007,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 { From 8ce08227b0cc10f16c3d59a25c432a615cb1864b Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Thu, 16 Jan 2020 15:06:54 +0200 Subject: [PATCH 169/666] #8691: improved language pack inheritance order --- .../Framework/App/Language/Dictionary.php | 71 +++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php index d9a5ccb00d892..9aaafc23c9e49 100644 --- a/lib/internal/Magento/Framework/App/Language/Dictionary.php +++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php @@ -103,7 +103,9 @@ public function getDictionary($languageCode) foreach ($languages as $languageConfig) { $this->collectInheritedPacks($languageConfig, $packs); } - uasort($packs, [$this, 'sortInherited']); + + // Get sorted packs + $packs = $this->getSortedPacks($packs); // Merge all packages of translation to one dictionary $result = []; @@ -118,6 +120,37 @@ public function getDictionary($languageCode) return $result; } + /** + * Get sorted packs + * + * First level packs (inheritance_level eq 0) sort by 'sort order' (ascending) + * Inherited packs has the same order as declared in parent config (language.xml) + * + * @param array $allPacks + * + * @return array + */ + private function getSortedPacks($allPacks) + { + // Get first level (inheritance_level) packs and sort by provided sort order (descending) + $firstLevelPacks = array_filter( + $allPacks, + function ($pack) { + return $pack['inheritance_level'] === 0; + } + ); + uasort($firstLevelPacks, [$this, 'sortPacks']); + + // Add inherited packs + $sortedPacks = []; + foreach ($firstLevelPacks as $pack) { + $this->addInheritedPacks($allPacks, $pack, $sortedPacks); + } + + // Reverse array: the first element has the lowest priority, the last one - the highest + return array_reverse($sortedPacks, true); + } + /** * Line up (flatten) a tree of inheritance of language packs * @@ -152,28 +185,42 @@ private function collectInheritedPacks($languageConfig, &$result, $level = 0, ar } /** - * Sub-routine for custom sorting packs using inheritance level and sort order + * Add inherited packs to sorted packs * - * First sort by inheritance level descending, then by sort order ascending + * @param array $packs + * @param array $pack + * @param array $sortedPacks + * + * @return void + */ + private function addInheritedPacks($packs, $pack, &$sortedPacks) + { + $sortedPacks[$pack['key']] = $pack; + foreach ($pack['language']->getUses() as $reuse) { + $packKey = implode('|', [$reuse['vendor'], $reuse['package']]); + if (isset($packs[$packKey])) { + $this->addInheritedPacks($packs, $packs[$packKey], $sortedPacks); + } + } + } + + /** + * Sub-routine for custom sorting packs using sort order (descending) * * @param array $current * @param array $next + * * @return int * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function sortInherited($current, $next) + private function sortPacks($current, $next) { - if ($current['inheritance_level'] > $next['inheritance_level']) { - return -1; - } elseif ($current['inheritance_level'] < $next['inheritance_level']) { - return 1; - } if ($current['sort_order'] > $next['sort_order']) { - return 1; - } elseif ($current['sort_order'] < $next['sort_order']) { return -1; + } elseif ($current['sort_order'] < $next['sort_order']) { + return 1; } - return strcmp($current['key'], $next['key']); + return strcmp($next['key'], $current['key']); } /** From b2177742d18ae320b07562b70b3358305c29fcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Eduardo=20C=C3=A1nepa=20Cihuelo?= <10290593+manuelcanepa@users.noreply.github.com> Date: Thu, 16 Jan 2020 10:14:20 -0300 Subject: [PATCH 170/666] Update app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php Co-Authored-By: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> --- app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php index 568774a112e9a..20dad6c0300f3 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php @@ -123,7 +123,7 @@ private function initEmptyFile(\DOMDocument $dom): \DOMElement * See COPYING.txt for license details. */ '); - $dom->appendChild($copyrigthComment); + $dom->appendChild($copyrightComment); $catalogNode = $dom->createElement('catalog'); $catalogNode->setAttribute('xmlns', self::XMLNS); From 4d70d26317de495f228604a26c63f3827ece3836 Mon Sep 17 00:00:00 2001 From: Manuel Canepa <manuelcanepa@gmail.com> Date: Thu, 16 Jan 2020 10:17:44 -0300 Subject: [PATCH 171/666] Fix typo --- app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php index 20dad6c0300f3..f45aebf6fad68 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/VsCode.php @@ -117,7 +117,7 @@ public function generateCatalog(array $dictionary, $configFile): void */ private function initEmptyFile(\DOMDocument $dom): \DOMElement { - $copyrigthComment = $dom->createComment(' + $copyrightComment = $dom->createComment(' /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. From fb90fd701cf37b24d9f678a74cc91488f27bee79 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 16 Jan 2020 16:00:35 +0200 Subject: [PATCH 172/666] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- .../Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml | 1 + ...ertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml | 4 ++++ .../Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) rename app/code/Magento/{Multishipping => Sales}/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml (91%) diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml index 26a1892cb679e..dbc1ba980e9c7 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -16,6 +16,7 @@ <description value="Verify that shipping price on My account matches with shipping method prices after multiple addresses checkout (Order view page)"/> <severity value="CRITICAL"/> <testCaseId value="MC-28900"/> + <useCaseId value="MC-19303"/> <group value="catalog"/> <group value="sales"/> <group value="multishipping"/> diff --git a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml similarity index 91% rename from app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml rename to app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml index 9281cdf03a1ab..b5361363c489b 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup.xml @@ -9,6 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <actionGroup name="AssertStorefrontCustomerOrderMatchesGrandTotalActionGroup"> + <annotations> + <description>Check that order grand total equals sum of all totals.</description> + </annotations> + <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('subtotal')}}" stepKey="grabValueForSubtotal"/> <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('shipping')}}" stepKey="grabValueForShippingHandling"/> <grabTextFrom selector="{{StorefrontSalesOrderSection.salesOrderPrice('grand_total')}}" stepKey="grabValueForGrandTotal"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml index 5b079891f657a..0964ef5811cec 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCustomerOrdersGridSection.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="StorefrontCustomerOrdersGridSection"> - <element name="orderView" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> - <element name="reorderBtn" type="button" selector="//td[text()='{{orderNumber}}']/following-sibling::td[@class='col actions']/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> + <element name="orderView" type="button" selector="//td[contains(text(),'{{orderNumber}}')]/following-sibling::td[contains(@class,'col') and contains(@class,'actions')]/a[contains(@class, 'view')]" parameterized="true" timeout="30" /> + <element name="reorderBtn" type="button" selector="//td[contains(text(),'{{orderNumber}}')]/following-sibling::td[contains(@class,'col') and contains(@class,'actions')]/a[contains(@class, 'order')]" parameterized="true" timeout="30" /> </section> </sections> From ca69fd22d5d644b6d5347aae5ef57407dfd49bd4 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 16 Jan 2020 16:30:22 +0200 Subject: [PATCH 173/666] MC-23546: Child Configurable product does not save disabled status via API --- .../StorefrontQuickSearchConfigurableChildrenTest.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml index 03ce878ef4f9f..1169d053ec7c8 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -14,8 +14,8 @@ <title value="User should be able to use Quick Search to a configurable product's child products"/> <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> - <testCaseId value="MC-14798"/> - <group value="CatalogSearch"/> + <testCaseId value="MC-28374"/> + <group value="catalogSearch"/> <group value="mtf_migrated"/> </annotations> <before> @@ -75,20 +75,19 @@ <magentoCLI command="indexer:reindex" stepKey="reindex"/> </before> <after> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigurableProduct"/> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToHomePage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> <argument name="phrase" value="$createConfigurableProduct.name$"/> </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> + <actionGroup ref="StorefrontQuickSearchSeeProductByNameActionGroup" stepKey="seeProductInGrid"> <argument name="productName" value="$createConfigurableProduct.name$"/> - <argument name="index" value="1"/> </actionGroup> <!-- Disable Child Product --> From 92816ab04db61666741ae9ab0986175068c46bee Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 16 Jan 2020 15:38:32 +0000 Subject: [PATCH 174/666] update getCustomer method in order class --- .../Magento/Sales/Api/Data/OrderInterface.php | 8 +++++++ app/code/Magento/Sales/Model/Order.php | 23 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index b45fddc7d7354..f699d24bd32cd 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Api\Data; +use Magento\Customer\Model\Customer; + /** * Order interface. * @@ -910,6 +912,12 @@ public function getCreatedAt(); */ public function setCreatedAt($createdAt); + /** + * Gets the customer from Order + * @return Customer + */ + public function getCustomer(); + /** * Gets the customer date-of-birth (DOB) for the order. * diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 89564f97ccf16..1d520574f21d7 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Model; use Magento\Config\Model\Config\Source\Nooptreq; +use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Directory\Model\Currency; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -51,7 +52,6 @@ * @method bool hasCustomerNoteNotify() * @method bool hasForcedCanCreditmemo() * @method bool getIsInProcess() - * @method \Magento\Customer\Model\Customer getCustomer() * @method \Magento\Sales\Model\Order setSendEmail(bool $value) * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) @@ -307,6 +307,11 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ private $scopeConfig; + /** + * @var CustomerRepositoryInterface + */ + private $_customerRepositoryInterface; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -340,6 +345,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param OrderItemRepositoryInterface $itemRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param ScopeConfigInterface $scopeConfig + * @param CustomerRepositoryInterface $customerRepositoryInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -366,6 +372,7 @@ public function __construct( \Magento\Sales\Model\ResourceModel\Order\Shipment\Track\CollectionFactory $trackCollectionFactory, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $salesOrderCollectionFactory, PriceCurrencyInterface $priceCurrency, + CustomerRepositoryInterface $customerRepositoryInterface, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productListFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -403,6 +410,7 @@ public function __construct( $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: ObjectManager::getInstance() ->get(SearchCriteriaBuilder::class); $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); + $this->_customerRepositoryInterface = $customerRepositoryInterface; parent::__construct( $context, @@ -562,6 +570,19 @@ public function getStore() return $this->_storeManager->getStore(); } + /** + * Returns Customer + * + * @return \Magento\Customer\Api\Data\CustomerInterface + * @throws LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function getCustomer() + { + $customerId = $this->getData(OrderInterface::CUSTOMER_ID); + return $this->_customerRepositoryInterface->getById($customerId); + } + /** * Retrieve order cancel availability * From d3dbceef5544a0fd7bb931669ed170112b915905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Thu, 16 Jan 2020 22:51:36 +0100 Subject: [PATCH 175/666] Module Catalog: Blocks --- .../Block/Product/ProductList/Related.php | 53 +++++++------ .../Block/Product/ProductList/Upsell.php | 76 ++++++++++--------- 2 files changed, 68 insertions(+), 61 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Related.php b/app/code/Magento/Catalog/Block/Product/ProductList/Related.php index 24811d61a7715..387fac770c5bc 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Related.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Related.php @@ -6,7 +6,15 @@ namespace Magento\Catalog\Block\Product\ProductList; +use Magento\Catalog\Block\Product\AbstractProduct; +use Magento\Catalog\Block\Product\Context; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Visibility as ProductVisibility; use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Checkout\Model\ResourceModel\Cart as CartResourceModel; +use Magento\Checkout\Model\Session as CheckoutSession; +use Magento\Framework\DataObject\IdentityInterface; +use Magento\Framework\Module\Manager; use Magento\Framework\View\Element\AbstractBlock; /** @@ -16,8 +24,7 @@ * @SuppressWarnings(PHPMD.LongVariable) * @since 100.0.2 */ -class Related extends \Magento\Catalog\Block\Product\AbstractProduct implements - \Magento\Framework\DataObject\IdentityInterface +class Related extends AbstractProduct implements IdentityInterface { /** * @var Collection @@ -27,53 +34,50 @@ class Related extends \Magento\Catalog\Block\Product\AbstractProduct implements /** * Checkout session * - * @var \Magento\Checkout\Model\Session + * @var CheckoutSession */ protected $_checkoutSession; /** * Catalog product visibility * - * @var \Magento\Catalog\Model\Product\Visibility + * @var ProductVisibility */ protected $_catalogProductVisibility; /** * Checkout cart * - * @var \Magento\Checkout\Model\ResourceModel\Cart + * @var CartResourceModel */ protected $_checkoutCart; /** - * @var \Magento\Framework\Module\Manager + * @var Manager */ protected $moduleManager; /** - * @param \Magento\Catalog\Block\Product\Context $context - * @param \Magento\Checkout\Model\ResourceModel\Cart $checkoutCart - * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility - * @param \Magento\Checkout\Model\Session $checkoutSession - * @param \Magento\Framework\Module\Manager $moduleManager + * @param Context $context + * @param CartResourceModel $checkoutCart + * @param ProductVisibility $catalogProductVisibility + * @param CheckoutSession $checkoutSession + * @param Manager $moduleManager * @param array $data */ public function __construct( - \Magento\Catalog\Block\Product\Context $context, - \Magento\Checkout\Model\ResourceModel\Cart $checkoutCart, - \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, - \Magento\Checkout\Model\Session $checkoutSession, - \Magento\Framework\Module\Manager $moduleManager, + Context $context, + CartResourceModel $checkoutCart, + ProductVisibility $catalogProductVisibility, + CheckoutSession $checkoutSession, + Manager $moduleManager, array $data = [] ) { $this->_checkoutCart = $checkoutCart; $this->_catalogProductVisibility = $catalogProductVisibility; $this->_checkoutSession = $checkoutSession; $this->moduleManager = $moduleManager; - parent::__construct( - $context, - $data - ); + parent::__construct($context, $data); } /** @@ -84,7 +88,7 @@ public function __construct( protected function _prepareData() { $product = $this->getProduct(); - /* @var $product \Magento\Catalog\Model\Product */ + /* @var $product Product */ $this->_itemCollection = $product->getRelatedProductCollection()->addAttributeToSelect( 'required_options' @@ -139,12 +143,11 @@ public function getItems() */ public function getIdentities() { - $identities = []; + $identities = [[]]; foreach ($this->getItems() as $item) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge - $identities = array_merge($identities, $item->getIdentities()); + $identities[] = $item->getIdentities(); } - return $identities; + return array_merge(...$identities); } /** diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php index fa1beaf6e0ea8..cf7e992650e1f 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php @@ -6,7 +6,16 @@ namespace Magento\Catalog\Block\Product\ProductList; +use Magento\Catalog\Block\Product\AbstractProduct; +use Magento\Catalog\Block\Product\Context; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Visibility as ProductVisibility; use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Checkout\Model\ResourceModel\Cart as CartResourceModel; +use Magento\Checkout\Model\Session as CheckoutSession; +use Magento\Framework\DataObject; +use Magento\Framework\DataObject\IdentityInterface; +use Magento\Framework\Module\Manager; /** * Catalog product upsell items block @@ -15,8 +24,7 @@ * @SuppressWarnings(PHPMD.LongVariable) * @since 100.0.2 */ -class Upsell extends \Magento\Catalog\Block\Product\AbstractProduct implements - \Magento\Framework\DataObject\IdentityInterface +class Upsell extends AbstractProduct implements IdentityInterface { /** * @var int @@ -24,7 +32,7 @@ class Upsell extends \Magento\Catalog\Block\Product\AbstractProduct implements protected $_columnCount = 4; /** - * @var \Magento\Framework\DataObject[] + * @var DataObject[] */ protected $_items; @@ -41,53 +49,50 @@ class Upsell extends \Magento\Catalog\Block\Product\AbstractProduct implements /** * Checkout session * - * @var \Magento\Checkout\Model\Session + * @var CheckoutSession */ protected $_checkoutSession; /** * Catalog product visibility * - * @var \Magento\Catalog\Model\Product\Visibility + * @var ProductVisibility */ protected $_catalogProductVisibility; /** * Checkout cart * - * @var \Magento\Checkout\Model\ResourceModel\Cart + * @var CartResourceModel */ protected $_checkoutCart; /** - * @var \Magento\Framework\Module\Manager + * @var Manager */ protected $moduleManager; /** - * @param \Magento\Catalog\Block\Product\Context $context - * @param \Magento\Checkout\Model\ResourceModel\Cart $checkoutCart - * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility - * @param \Magento\Checkout\Model\Session $checkoutSession - * @param \Magento\Framework\Module\Manager $moduleManager + * @param Context $context + * @param CartResourceModel $checkoutCart + * @param ProductVisibility $catalogProductVisibility + * @param CheckoutSession $checkoutSession + * @param Manager $moduleManager * @param array $data */ public function __construct( - \Magento\Catalog\Block\Product\Context $context, - \Magento\Checkout\Model\ResourceModel\Cart $checkoutCart, - \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, - \Magento\Checkout\Model\Session $checkoutSession, - \Magento\Framework\Module\Manager $moduleManager, + Context $context, + CartResourceModel $checkoutCart, + ProductVisibility $catalogProductVisibility, + CheckoutSession $checkoutSession, + Manager $moduleManager, array $data = [] ) { $this->_checkoutCart = $checkoutCart; $this->_catalogProductVisibility = $catalogProductVisibility; $this->_checkoutSession = $checkoutSession; $this->moduleManager = $moduleManager; - parent::__construct( - $context, - $data - ); + parent::__construct($context, $data); } /** @@ -98,7 +103,7 @@ public function __construct( protected function _prepareData() { $product = $this->getProduct(); - /* @var $product \Magento\Catalog\Model\Product */ + /* @var $product Product */ $this->_itemCollection = $product->getUpSellProductCollection()->setPositionOrder()->addStoreFilter(); if ($this->moduleManager->isEnabled('Magento_Checkout')) { $this->_addProductAttributesAndPrices($this->_itemCollection); @@ -153,7 +158,7 @@ public function getItemCollection() /** * Get collection items * - * @return \Magento\Framework\DataObject[] + * @return DataObject[] */ public function getItems() { @@ -181,8 +186,8 @@ public function getRowCount() */ public function setColumnCount($columns) { - if ((int) $columns > 0) { - $this->_columnCount = (int) $columns; + if ((int)$columns > 0) { + $this->_columnCount = (int)$columns; } return $this; } @@ -227,12 +232,12 @@ public function getIterableItem() * * @param string $type * @param int $limit - * @return \Magento\Catalog\Block\Product\ProductList\Upsell + * @return Upsell */ public function setItemLimit($type, $limit) { - if ((int) $limit > 0) { - $this->_itemLimits[$type] = (int) $limit; + if ((int)$limit > 0) { + $this->_itemLimits[$type] = (int)$limit; } return $this; } @@ -250,9 +255,9 @@ public function getItemLimit($type = '') } if (isset($this->_itemLimits[$type])) { return $this->_itemLimits[$type]; - } else { - return 0; } + + return 0; } /** @@ -262,11 +267,10 @@ public function getItemLimit($type = '') */ public function getIdentities() { - $identities = []; - foreach ($this->getItems() as $item) { - // phpcs:ignore Magento2.Performance.ForeachArrayMerge - $identities = array_merge($identities, $item->getIdentities()); - } - return $identities; + $identities = array_map(function (DataObject $item) { + return $item->getIdentities(); + }, $this->getItems()); + + return array_merge(...$identities); } } From 2481c0bd065488d75f23a7f3769a0c7bc2cfecc1 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Fri, 17 Jan 2020 11:06:00 +0200 Subject: [PATCH 176/666] MC-29047: Fix MFTF test --- ...ml => StorefrontOpenProductFromCategoryPageActionGroup.xml} | 2 +- ...yConfigurableProductChildAssignedToSeparateCategoryTest.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename app/code/Magento/Catalog/Test/Mftf/ActionGroup/{StorefrontCategoryPageOpenProductActionGroup.xml => StorefrontOpenProductFromCategoryPageActionGroup.xml} (91%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml similarity index 91% rename from app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml rename to app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml index 86ce7a602315d..39bffe006d987 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCategoryPageOpenProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontOpenProductFromCategoryPageActionGroup.xml @@ -7,7 +7,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontCategoryPageOpenProductActionGroup"> + <actionGroup name="StorefrontOpenProductFromCategoryPageActionGroup"> <annotations> <description>Click on the provided product on category page.</description> </annotations> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml index 5f2fc5c8caca7..56e5bedc9eab1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest.xml @@ -17,6 +17,7 @@ <severity value="CRITICAL"/> <testCaseId value="MC-25651"/> <group value="configurable_product"/> + <group value="catalog"/> </annotations> <before> <!-- Create the category --> @@ -123,7 +124,7 @@ <actionGroup ref="StorefrontCheckProductIsMissingInCategoryProductsPageActionGroup" stepKey="dontSeeParentProduct"> <argument name="productName" value="$$createConfigProduct.name$$"/> </actionGroup> - <actionGroup ref="StorefrontCategoryPageOpenProductActionGroup" stepKey="openConfigChildProductFromCategoryPage"> + <actionGroup ref="StorefrontOpenProductFromCategoryPageActionGroup" stepKey="openConfigChildProductFromCategoryPage"> <argument name="productName" value="$$createConfigChildProduct1.name$$"/> </actionGroup> <actionGroup ref="AssertStorefrontProductDetailPageNameAndUrlActionGroup" stepKey="checkStorefrontConfigChildProductPage"> From 74ad5dd1ef05eab9d0b4fa26a1303f8ea3fa0c52 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 17 Jan 2020 11:46:55 +0200 Subject: [PATCH 177/666] Unit Test for Magento\Sitemap\Model\Config\Backend\Priority --- .../Model/Config/Backend/PriorityTest.php | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php new file mode 100644 index 0000000000000..eea98e0f966ee --- /dev/null +++ b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php @@ -0,0 +1,81 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sitemap\Test\Unit\Model\Config\Backend; + +use Magento\Sitemap\Model\Config\Backend\Priority; +use PHPUnit\Framework\MockObject\MockObject; + +/** + * Tests for @see Priority + */ +class PriorityTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var Priority|MockObject + */ + private $priorityMock; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->priorityMock = $this->getMockBuilder(Priority::class) + ->disableOriginalConstructor() + ->setMethods(['getValue']) + ->getMock(); + } + + /** + * @param string $value + * @dataProvider dataProviderTestBeforeSaveValueCorrect + */ + public function testBeforeSave($value) + { + $this->priorityMock->expects($this->once()) + ->method('getValue') + ->willReturn($value); + + $this->assertSame($this->priorityMock, $this->priorityMock->beforeSave()); + } + + /** + * @param string $value + * @dataProvider dataProviderTestBeforeSaveValueOutOfRange + */ + public function testBeforeSaveValueOutOfRange($value) + { + $this->priorityMock->expects($this->once()) + ->method('getValue') + ->willReturn($value); + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('The priority must be between 0 and 1.'); + + $this->priorityMock->beforeSave(); + } + + /** + * @return array + */ + public function dataProviderTestBeforeSaveValueCorrect() + { + return [ + ['0'], ['0.0'], ['0.5'], ['1'] + ]; + } + + /** + * @return array + */ + public function dataProviderTestBeforeSaveValueOutOfRange() + { + return [ + ['-1'], ['2'], ['nan'] + ]; + } +} From 162622f66cba3dc7cb45a2162384df967edd6542 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 17 Jan 2020 12:50:05 +0200 Subject: [PATCH 178/666] MC-30510: [Integration] PaymentFailuresServiceTest::testHandlerWithCustomer is flaky --- .../Service/PaymentFailuresServiceTest.php | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php index 383af7968e047..c85408f21819a 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php @@ -7,10 +7,12 @@ namespace Magento\Sales\Model\Service; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Model\Quote; use Magento\Sales\Api\PaymentFailuresInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\MockObject\MockObject; /** * Tests \Magento\Sales\Api\PaymentFailuresInterface. @@ -28,10 +30,15 @@ class PaymentFailuresServiceTest extends \PHPUnit\Framework\TestCase private $quote; /** - * @var CartRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CartRepositoryInterface|MockObject */ private $cartRepositoryMock; + /** + * @var TimezoneInterface|MockObject + */ + private $localeDateMock; + /** * @inheritdoc */ @@ -42,11 +49,15 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['get']) ->getMockForAbstractClass(); + $this->localeDateMock = $this->getMockBuilder(TimezoneInterface::class) + ->setMethods(['formatDateTime']) + ->getMockForAbstractClass(); $this->paymentFailures = Bootstrap::getObjectManager()->create( PaymentFailuresInterface::class, [ 'cartRepository' => $this->cartRepositoryMock, + 'localeDate' => $this->localeDateMock, ] ); } @@ -69,20 +80,19 @@ public function testHandlerWithCustomer(): void ->with($this->quote->getId()) ->willReturn($this->quote); + $dateAndTime = 'Nov 22, 2019, 1:00:00 AM'; + $this->localeDateMock->expects($this->atLeastOnce())->method('formatDateTime')->willReturn($dateAndTime); $this->paymentFailures->handle((int)$this->quote->getId(), $errorMessage->render()); $paymentReflection = new \ReflectionClass($this->paymentFailures); - $templateTimeMethod = $paymentReflection->getMethod('getLocaleDate'); - $templateTimeMethod->setAccessible(true); - $templateVarsMethod = $paymentReflection->getMethod('getTemplateVars'); $templateVarsMethod->setAccessible(true); $templateVars = $templateVarsMethod->invoke($this->paymentFailures, $this->quote, $errorMessage, $checkoutType); $expectedVars = [ - 'reason' => $errorMessage, + 'reason' => $errorMessage->render(), 'checkoutType' => $checkoutType, - 'dateAndTime' => $templateTimeMethod->invoke($this->paymentFailures), + 'dateAndTime' => $dateAndTime, 'customer' => 'John Smith', 'customerEmail' => 'aaa@aaa.com', 'paymentMethod' => 'Some Title Of The Method', From fd3fc0ed50de0d057735e9abb2962513d3d54049 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 17 Jan 2020 12:55:10 +0200 Subject: [PATCH 179/666] improve test name --- .../Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php index eea98e0f966ee..bba2429912cd8 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php @@ -34,7 +34,7 @@ protected function setUp() * @param string $value * @dataProvider dataProviderTestBeforeSaveValueCorrect */ - public function testBeforeSave($value) + public function testBeforeSaveIsChainable($value) { $this->priorityMock->expects($this->once()) ->method('getValue') From 1df821646fbcb7a626a4705734132d982d895bba Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 17 Jan 2020 13:51:44 +0200 Subject: [PATCH 180/666] Static test fix --- .../Test/Unit/Model/Config/Backend/PriorityTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php index bba2429912cd8..b819dfd343806 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/Config/Backend/PriorityTest.php @@ -31,6 +31,8 @@ protected function setUp() } /** + * Verify before save in chainable + * * @param string $value * @dataProvider dataProviderTestBeforeSaveValueCorrect */ @@ -44,6 +46,8 @@ public function testBeforeSaveIsChainable($value) } /** + * Verify before save value out of range + * * @param string $value * @dataProvider dataProviderTestBeforeSaveValueOutOfRange */ @@ -60,6 +64,8 @@ public function testBeforeSaveValueOutOfRange($value) } /** + * Data provider + * * @return array */ public function dataProviderTestBeforeSaveValueCorrect() @@ -70,6 +76,8 @@ public function dataProviderTestBeforeSaveValueCorrect() } /** + * Data provider + * * @return array */ public function dataProviderTestBeforeSaveValueOutOfRange() From 819c3f255224d7e2d04e90bcd47bb410a2eee23b Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Fri, 17 Jan 2020 14:31:45 +0200 Subject: [PATCH 181/666] #18012: added i18n wrapper to be used in underscore templates for translation --- lib/web/mage/translate.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/translate.js b/lib/web/mage/translate.js index 65ec33266aebd..b96586ab9e927 100644 --- a/lib/web/mage/translate.js +++ b/lib/web/mage/translate.js @@ -6,8 +6,9 @@ define([ 'jquery', 'mage/mage', - 'mageTranslationDictionary' -], function ($, mage, dictionary) { + 'mageTranslationDictionary', + 'underscore' +], function ($, mage, dictionary, _) { 'use strict'; $.extend(true, $, { @@ -46,5 +47,12 @@ define([ }); $.mage.__ = $.proxy($.mage.translate.translate, $.mage.translate); + // Provide i18n wrapper to be used in underscore templates for translation + _.extend(_, { + i18n: function (str) { + return $.mage.__(str); + } + }); + return $.mage.__; }); From f3c0c6f7dacbf711f864e8e7764af916a25d47b3 Mon Sep 17 00:00:00 2001 From: Tjitse <Tjitse@vendic.nl> Date: Fri, 17 Jan 2020 13:37:49 +0100 Subject: [PATCH 182/666] Fix typo in sitemap product collection docblock --- .../Magento/Sitemap/Model/ResourceModel/Catalog/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php index 23a1c0fd09b7b..8b2154e6ee47a 100644 --- a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php +++ b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php @@ -291,7 +291,7 @@ protected function _getAttribute($attributeCode) } /** - * Get category collection array + * Get product collection array * * @param null|string|bool|int|Store $storeId * From d6eff7b04bbbfd20fbb71a793daef5c93edb998e Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Fri, 17 Jan 2020 16:53:44 +0200 Subject: [PATCH 183/666] MC-24168: Fix Skipped MFTF Tests From MC-17140: MAGETWO-95175, MAGETWO-97001, MAGETWO-98189 --- .../Catalog/Test/Mftf/Data/ConstData.xml | 2 + .../Section/AdminCategoryProductsSection.xml | 4 +- ...ateCategoryProductUrlRewriteConfigData.xml | 22 +++ ...OpenCreditMemoFromOrderPageActionGroup.xml | 20 +++ ...minOpenInvoiceFromOrderPageActionGroup.xml | 20 +++ ...inOpenShipmentFromOrderPageActionGroup.xml | 20 +++ ...eateCreditMemoFromOrderPageActionGroup.xml | 19 +++ ...rtAdminCreditMemoGrandTotalActionGroup.xml | 21 +++ .../Section/AdminOrderShipmentsTabSection.xml | 3 +- ...axRuleCustomProductTaxClassActionGroup.xml | 31 ++++ .../Tax/Test/Mftf/Data/TaxConfigData.xml | 6 + .../Mftf/Section/AdminTaxRulesSection.xml | 1 + .../Test/AdminCheckCreditMemoTotalsTest.xml | 91 +++++++++++ .../Mftf/Test/CheckCreditMemoTotalsTest.xml | 148 ------------------ 14 files changed, 258 insertions(+), 150 deletions(-) create mode 100644 app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml create mode 100644 app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml create mode 100644 app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml delete mode 100644 app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml index d09880f14afbf..f44bfb217d0ae 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml @@ -16,5 +16,7 @@ <entity name="prodNameWithSpecChars"> <data key="trademark">"Pursuit Lumaflex™ Tone Band"</data> <data key="skumark">"x™"</data> + <data key="trademark_without_quotes">Pursuit Lumaflex™ Tone Band</data> + <data key="skumark_without_quotes">x™</data> </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml index 8a993a74a58d1..d89d9a5bd43c0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml @@ -12,5 +12,7 @@ <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"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml new file mode 100644 index 0000000000000..10d2213b64717 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Mftf/Data/GenerateCategoryProductUrlRewriteConfigData.xml @@ -0,0 +1,22 @@ +<?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="EnableGenerateCategoryProductUrlRewritesConfigData"> + <!-- Default value --> + <data key="path">catalog/seo/generate_category_product_rewrites</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisableGenerateCategoryProductUrlRewritesConfigData"> + <data key="path">catalog/seo/generate_category_product_rewrites</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..fab25c7f40681 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenCreditMemoFromOrderPageActionGroup.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="AdminOpenCreditMemoFromOrderPageActionGroup"> + <annotations> + <description>Admin open creditmemo from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.creditMemos}}" dependentSelector="{{AdminOrderCreditMemosTabSection.viewGridRow('1')}}" visible="false" stepKey="openCreditMemosTab"/> + <waitForElementVisible selector="{{AdminCreditMemoTotalSection.viewMemo}}" stepKey="waitForCreditMemosTabOpened"/> + <click selector="{{AdminOrderCreditMemosTabSection.viewGridRow('1')}}" stepKey="viewMemo"/> + <waitForPageLoad stepKey="waitForCreditMemoOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..ec4352c15e1a8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenInvoiceFromOrderPageActionGroup.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="AdminOpenInvoiceFromOrderPageActionGroup"> + <annotations> + <description>Admin open invoice from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.invoices}}" dependentSelector="{{AdminOrderInvoicesTabSection.viewInvoice}}" visible="false" stepKey="openInvoicesTab"/> + <waitForElementVisible selector="{{AdminOrderInvoicesTabSection.viewInvoice}}" stepKey="waitForInvocesTabOpened"/> + <click selector="{{AdminOrderInvoicesTabSection.viewGridRow('1')}}" stepKey="viewInvoice"/> + <waitForPageLoad stepKey="waitForInvoiceOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..1ed31b93cb075 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOpenShipmentFromOrderPageActionGroup.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="AdminOpenShipmentFromOrderPageActionGroup"> + <annotations> + <description>Admin open shipment from order</description> + </annotations> + <conditionalClick selector="{{AdminOrderDetailsOrderViewSection.shipments}}" dependentSelector="{{AdminOrderShipmentsTabSection.viewShipment}}" visible="false" stepKey="openShipmentsTab"/> + <waitForElementVisible selector="{{AdminOrderShipmentsTabSection.viewShipment}}" stepKey="waitForShipmentTabOpened"/> + <click selector="{{AdminOrderShipmentsTabSection.viewGridRow('1')}}" stepKey="viewShipment"/> + <waitForPageLoad stepKey="waitForShipmentOpened"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.xml new file mode 100644 index 0000000000000..e5c29ac33294e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminStartToCreateCreditMemoFromOrderPageActionGroup.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="AdminStartToCreateCreditMemoFromOrderPageActionGroup"> + <annotations> + <description>Admin start to create credit memo from order</description> + </annotations> + <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreditMemo"/> + <waitForElementVisible selector="{{AdminHeaderSection.pageTitle}}" stepKey="waitForPageTitle"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoPageTitle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.xml new file mode 100644 index 0000000000000..f318e76ce74a8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertAdminCreditMemoGrandTotalActionGroup.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="AssertAdminCreditMemoGrandTotalActionGroup"> + <annotations> + <description>Admin assert creditmemo grant total sum</description> + </annotations> + <arguments> + <argument name="expectedGrandTotal" type="string" defaultValue="$123.00"/> + </arguments> + <grabTextFrom selector="{{AdminCreditMemoTotalSection.grandTotal}}" stepKey="getGrandTotal"/> + <assertEquals expected='{{expectedGrandTotal}}' actualType="variable" expectedType="string" actual="getGrandTotal" stepKey="assertGrandTotalValue"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml index e471fcfe18114..66bea45b83f3d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml @@ -18,5 +18,6 @@ <element name="shipmentId" type="input" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//input[@name='increment_id']" timeout="30"/> <element name="totalQtyFrom" type="input" selector="[name='total_qty[from]']" timeout="30"/> <element name="totalQtyTo" type="input" selector="[name='total_qty[to]']" timeout="30"/> + <element name="viewShipment" type="button" selector="#sales_order_view_tabs_order_shipments_content div.admin__data-grid-wrap a.action-menu-item" timeout="30"/> </section> -</sections> \ No newline at end of file +</sections> diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.xml new file mode 100644 index 0000000000000..377985a81af37 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/AdminCreateTaxRuleCustomProductTaxClassActionGroup.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="AdminCreateTaxRuleCustomProductTaxClassActionGroup"> + <annotations> + <description>Admin create tax rule with custom tax rate and product tax class</description> + </annotations> + <arguments> + <argument name="taxRuleCode" type="string" defaultValue="{{defaultTaxRule.code}}"/> + <argument name="taxRateCode" type="string" defaultValue="{{US_NY_Rate_1.code}}"/> + <argument name="productTaxClassName" type="string" defaultValue="NewTaxClass"/> + </arguments> + <amOnPage url="{{AdminNewTaxRulePage.url}}" stepKey="goNewTaxRulePage"/> + <waitForPageLoad stepKey="waitForNewTaxRulePageLoaded"/> + <fillField selector="{{AdminTaxRulesSection.ruleName}}" userInput="{{taxRuleCode}}" stepKey="fillRuleName"/> + <click selector="{{AdminTaxRulesSection.selectTaxRate(taxRateCode)}}" stepKey="selectTaxRate"/> + <click selector="{{AdminTaxRuleFormSection.additionalSettings}}" stepKey="clickAdditionalSettings"/> + <click selector="{{AdminTaxRulesSection.selectProductTaxClass(taxableGoodsTaxClass.class_name)}}" stepKey="unSelectTaxClass"/> + <click selector="{{AdminTaxRulesSection.selectProductTaxClass(productTaxClassName)}}" stepKey="selectProductTaxClass"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/> + <waitForElementVisible selector="{{AdminMessagesSection.successMessage}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You saved the tax rule." stepKey="verifyRuleSaved"/> + </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 4edf005c2fc2b..ad92bae51d429 100644 --- a/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml +++ b/app/code/Magento/Tax/Test/Mftf/Data/TaxConfigData.xml @@ -57,4 +57,10 @@ <entity name="EmptyField" type="taxPostCodeEmpty"> <data key="value"/> </entity> + <entity name="DefaultProductTaxClass"> + <!-- Default value --> + <data key="path">tax/classes/default_product_tax_class</data> + <data key="label">Yes</data> + <data key="value">2</data> + </entity> </entities> diff --git a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml index 7f721d4079c27..c69d555d5177a 100644 --- a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml +++ b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml @@ -35,5 +35,6 @@ <element name="taxRateMultiSelectItems" type="block" selector=".mselect-list-item"/> <element name="taxRateNumber" type="button" selector="//div[@data-ui-id='tax-rate-form-fieldset-element-form-field-tax-rate']//div[@class='mselect-items-wrapper']//label[{{var}}]" parameterized="true"/> <element name="selectTaxRate" type="input" selector="//span[text()='{{taxCode}}']" parameterized="true"/> + <element name="selectProductTaxClass" type="input" selector="//div[contains(@class, 'field-tax_product_class')]//*[contains(@class, 'mselect-list-item') and contains(.,'{{taxClass}}')]" 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 new file mode 100644 index 0000000000000..39e6e316dd486 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -0,0 +1,91 @@ +<?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="AdminCheckCreditMemoTotalsTest"> + <annotations> + <features value="Tax"/> + <stories value="Credit memo entity"/> + <title value="Checking Credit memo Totals"/> + <description value="Checking Credit memo Totals"/> + <severity value="MAJOR"/> + <testCaseId value="MC-6159"/> + <group value="tax"/> + <group value="sales"/> + </annotations> + <before> + <!-- Create productTaxClass --> + <createData entity="productTaxClass" stepKey="createProductTaxClass"/> + <!--Set configs--> + <magentoCLI command="config:set {{DisableGenerateCategoryProductUrlRewritesConfigData.path}} {{DisableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="disableGenerateUrlRewrite"/> + <magentoCLI command="config:set {{DefaultProductTaxClass.path}} $createProductTaxClass.return$" stepKey="setDefaultProductTaxClass"/> + <!--Create category and product--> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="productTaxClass">$createProductTaxClass.taxClass[class_name]$</field> + </createData> + <!--Create customer--> + <createData entity="Simple_US_Customer_NY" stepKey="createCustomer"/> + <!--Login as admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Create tax rule--> + <actionGroup ref="AdminCreateTaxRuleCustomProductTaxClassActionGroup" stepKey="createTaxRuleCustomProductTaxClass"> + <argument name="productTaxClassName" value="$createProductTaxClass.taxClass[class_name]$"/> + </actionGroup> + </before> + <after> + <!--Set configs--> + <magentoCLI command="config:set {{EnableGenerateCategoryProductUrlRewritesConfigData.path}} {{EnableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="enableGenerateUrlRewrite"/> + <magentoCLI command="config:set {{DefaultProductTaxClass.path}} {{DefaultProductTaxClass.value}}" stepKey="setDefaultProductTaxClass"/> + <!--Delete category and product--> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <!--Delete customer--> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <!-- Reset admin order filter --> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> + <!-- Go to the tax rule page and delete the row we created--> + <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulesPage"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteRule"> + <argument name="name" value="{{defaultTaxRule.code}}"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> + </actionGroup> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearTaxRuleFilter"/> + <!-- Delete Tax Class --> + <deleteData createDataKey="createProductTaxClass" stepKey="deleteProductTaxClass"/> + <!--Logout--> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </after> + <!--Create new order--> + <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="createNewOrder"> + <argument name="customer" value="Simple_US_Customer_NY"/> + </actionGroup> + <!--Add product to order--> + <actionGroup ref="AddSimpleProductToOrderActionGroup" stepKey="addSimpleProductToOrder"> + <argument name="product" value="$createSimpleProduct$"/> + </actionGroup> + <!--Set shipping method--> + <actionGroup ref="OrderSelectFlatRateShippingActionGroup" stepKey="orderSelectFlatRateShipping"/> + <!--Submit order--> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + <!--Create order invoice--> + <actionGroup ref="StartCreateInvoiceFromOrderPageActionGroup" stepKey="startCreateInvoice"/> + <actionGroup ref="SubmitInvoiceActionGroup" stepKey="submitInvoice"/> + <!--Create Credit Memo--> + <actionGroup ref="AdminStartToCreateCreditMemoFromOrderPageActionGroup" stepKey="startCreatingCreditMemo"/> + <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> + <actionGroup ref="UpdateCreditMemoTotalsActionGroup" stepKey="updateTotals"/> + <actionGroup ref="SubmitCreditMemoActionGroup" stepKey="submitCreditMemo"/> + <actionGroup ref="AdminOpenCreditMemoFromOrderPageActionGroup" stepKey="openCreditMemoFromOrderPageActionGroup"/> + <actionGroup ref="AssertAdminCreditMemoGrandTotalActionGroup" stepKey="assertGrandTotal"> + <argument name="expectedGrandTotal" value="$133.30"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml deleted file mode 100644 index e7964a2dd29eb..0000000000000 --- a/app/code/Magento/Tax/Test/Mftf/Test/CheckCreditMemoTotalsTest.xml +++ /dev/null @@ -1,148 +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="CheckCreditMemoTotalsTest"> - <annotations> - <features value="Tax"/> - <stories value="MAGETWO-91769 - Credit Memo - Wrong tax calculation! #10982"/> - <title value="Checking Credit memo Totals"/> - <description value="Checking Credit memo Totals"/> - <severity value="MAJOR"/> - <testCaseId value="MAGETWO-95175"/> - <group value="creditMemo"/> - <group value="tax"/> - <skip> - <issueId value="MC-17140"/> - </skip> - </annotations> - <before> - <!--Create category and product--> - <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="_defaultProduct" stepKey="createSimpleProduct"> - <requiredEntity createDataKey="createCategory"/> - </createData> - <!--Create customer--> - <createData entity="Simple_US_Customer_NY" stepKey="createCustomer"/> - <!--Login as admin--> - <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> - <!--Create tax rule and tax rate--> - <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulePage"/> - <waitForPageLoad stepKey="waitForTaxRatePage"/> - <click stepKey="addNewTaxRate" selector="{{AdminGridMainControls.add}}"/> - <fillField stepKey="fillRuleName" selector="{{AdminTaxRulesSection.ruleName}}" userInput="SampleRule"/> - <actionGroup ref="addCustomTaxRate" stepKey="addCustomTaxRate"> - <argument name="taxCode" value="SimpleTaxNY"/> - </actionGroup> - <click stepKey="expandAdditionalSettings" selector="{{AdminProductTaxClassSection.additionalSettings}}"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <click selector="{{AdminProductTaxClassSection.productTaxClass}}" stepKey="ClickToAddTaxClass"/> - <fillField selector="{{AdminProductTaxClassSection.TaxClassName}}" userInput="NewTaxClass" stepKey="setName"/> - <click selector="{{AdminProductTaxClassSection.confirm}}" stepKey="ClickToDone"/> - <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <waitForPageLoad stepKey="waitForTaxRatePage1"/> - <see userInput="You saved the tax rule." stepKey="VerifyRuleSaved"/> - <!--Search and edit product to add new created tax rule--> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="OpenEditProductOnBackend"> - <argument name="product" value="$$createSimpleProduct$$"/> - </actionGroup> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <selectOption selector="{{AdminProductFormActionSection.selectTaxClass}}" userInput="NewTaxClass" stepKey="SetNewTaxClass" /> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> - <!--Set configs--> - <amOnPage url="{{AdminTaxConfigurationPage.url}}" stepKey="goToTaxConfigPage"/> - <conditionalClick stepKey="clickOrdersInvoicesCreditSales" selector="{{AdminConfigureTaxSection.taxClasses}}" dependentSelector="{{AdminConfigureTaxSection.taxClassesCondition}}" visible="false"/> - <click selector="{{AdminConfigureTaxSection.useSystemValue}}" stepKey="UncheckUseSystemValue"/> - <selectOption selector="{{AdminConfigureTaxSection.productTaxClass}}" userInput="NewTaxClass" stepKey="selectClass"/> - <click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/> - <!--flash cache--> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <after> - <!--Delete category and product--> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <!--Delete customer--> - <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> - <!-- Reset admin order filter --> - <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderFilters"/> - <!--Roll Back configuration--> - <amOnPage url="{{AdminTaxConfigurationPage.url}}" stepKey="goToTaxConfigPage"/> - <conditionalClick stepKey="clickOrdersInvoicesCreditSales" selector="{{AdminConfigureTaxSection.taxClasses}}" dependentSelector="{{AdminConfigureTaxSection.taxClassesCondition}}" visible="false"/> - <selectOption selector="{{AdminConfigureTaxSection.productTaxClass}}" userInput="Taxable Goods" stepKey="selectClass"/> - <click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/> - <!-- Go to the tax rule page and delete the row we created--> - <amOnPage url="{{AdminTaxRuleGridPage.url}}" stepKey="goToTaxRulesPage"/> - <waitForPageLoad stepKey="waitForRulesPage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteRule"> - <argument name="name" value="SampleRule"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> - </actionGroup> - <!-- Go to the tax rate page --> - <amOnPage url="{{AdminTaxRateGridPage.url}}" stepKey="goToTaxRatesPage"/> - <waitForPageLoad stepKey="waitForRatesPage"/> - <!-- Delete tax rate that were created --> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deleteNYRate"> - <argument name="name" value="{{SimpleTaxNY.state}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.taxIdentifierSearch}}"/> - </actionGroup> - <actionGroup ref="DeleteProductTaxClassActionGroup" stepKey="deleteFirstProductTaxClass"> - <argument name="taxClassName" value="NewTaxClass"/> - </actionGroup> - <!--logout--> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <!--Create new order--> - <actionGroup stepKey="CreateNewOrder" ref="NavigateToNewOrderPageExistingCustomerActionGroup"> - <argument name="customer" value="Simple_US_Customer_NY"/> - </actionGroup> - <!--Add product to order--> - <click stepKey="clickToAddProduct" selector="{{AdminOrderFormItemsSection.addProducts}}"/> - <waitForPageLoad stepKey="waitForProductsOpened"/> - <checkOption selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" stepKey="selectProduct"/> - <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <!--Set shipping method--> - <actionGroup stepKey="OrderSelectFlatRateShippingActionGroup" ref="OrderSelectFlatRateShippingActionGroup"/> - <!--Submit order--> - <click stepKey="SubmitOrder" selector="{{AdminOrderFormActionSection.SubmitOrder}}"/> - <waitForPageLoad stepKey="waitForPageLoad4"/> - <grabTextFrom stepKey="getOrderId" selector="|Order # (\d+)|"/> - <!--Open new created order--> - <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> - <waitForPageLoad stepKey="waitForPageLoad5"/> - <actionGroup ref="FilterOrderGridByIdActionGroup" stepKey="filterOrderGridById"> - <argument name="orderId" value="$getOrderId"/> - </actionGroup> - <!--Create order invoice--> - <click selector="{{AdminDataGridTableSection.rowViewAction('1')}}" stepKey="clickCreatedOrderInGrid"/> - <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> - <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seePageNameNewInvoicePage"/> - <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeInvoiceCreateSuccess"/> - <see selector="{{AdminInvoiceOrderInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderProcessing"/> - <!--Create Credit Memo--> - <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreditMemoAction"/> - <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> - <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoInPageTitle"/> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the credit memo." stepKey="seeCreditMemoSuccess"/> - <click selector="{{AdminCreditMemoTotalSection.creditMemoItem}}" stepKey="goToCreatedCreditMemo"/> - <waitForPageLoad stepKey="waitForPageLoad6"/> - <!--View created memo and verify tax for product--> - <click selector="{{AdminCreditMemoTotalSection.viewMemo}}" stepKey="ViewMemo"/> - <waitForPageLoad stepKey="waitForPageLoad7"/> - <grabTextFrom selector="{{AdminCreditMemoTotalSection.grandTotal}}" stepKey="getGrandTotal"/> - <assertEquals expected='$123.00' expectedType="string" actual="($getGrandTotal)" stepKey="assertGrandTotalValue"/> - - </test> -</tests> From c103950be1f559c4ec89d0aa1709081e802c4348 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Fri, 17 Jan 2020 02:17:13 +0200 Subject: [PATCH 184/666] magento/magento2#: Unit test for \Magento\Bundle\Observer\AppendUpsellProductsObserver --- .../Observer/AppendUpsellProductsObserver.php | 13 +- .../AppendUpsellProductsObserverTest.php | 410 ++++++++++++++++++ 2 files changed, 421 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Observer/AppendUpsellProductsObserverTest.php diff --git a/app/code/Magento/Bundle/Observer/AppendUpsellProductsObserver.php b/app/code/Magento/Bundle/Observer/AppendUpsellProductsObserver.php index 63ae3cef7a33e..fe5eaebbf7f25 100644 --- a/app/code/Magento/Bundle/Observer/AppendUpsellProductsObserver.php +++ b/app/code/Magento/Bundle/Observer/AppendUpsellProductsObserver.php @@ -7,6 +7,9 @@ use Magento\Framework\Event\ObserverInterface; +/** + * Class adds bundle products into up-sell products collection + */ class AppendUpsellProductsObserver implements ObserverInterface { /** @@ -98,9 +101,15 @@ public function execute(\Magento\Framework\Event\Observer $observer) } /* @var $bundleCollection \Magento\Catalog\Model\ResourceModel\Product\Collection */ - $bundleCollection = $product->getCollection()->addAttributeToSelect( + $bundleCollection = $product->getCollection(); + $bundleCollection->addAttributeToSelect( $this->config->getProductAttributes() - )->addStoreFilter()->addMinimalPrice()->addFinalPrice()->addTaxPercents()->setVisibility( + ); + $bundleCollection->addStoreFilter(); + $bundleCollection->addMinimalPrice(); + $bundleCollection->addFinalPrice(); + $bundleCollection->addTaxPercents(); + $bundleCollection->setVisibility( $this->productVisibility->getVisibleInCatalogIds() ); diff --git a/app/code/Magento/Bundle/Test/Unit/Observer/AppendUpsellProductsObserverTest.php b/app/code/Magento/Bundle/Test/Unit/Observer/AppendUpsellProductsObserverTest.php new file mode 100644 index 0000000000000..d1058ff56270c --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Observer/AppendUpsellProductsObserverTest.php @@ -0,0 +1,410 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Bundle\Test\Unit\Observer; + +use Magento\Bundle\Helper\Data as BundleHelper; +use Magento\Bundle\Model\ResourceModel\Selection; +use Magento\Bundle\Observer\AppendUpsellProductsObserver; +use Magento\Catalog\Model\Config as CatalogConfig; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; +use Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection as ProductLinkCollection; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\GroupedProduct\Model\Product\Type\Grouped; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test class for \Magento\Bundle\Observer\AppendUpsellProductsObserver + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class AppendUpsellProductsObserverTest extends TestCase +{ + /** + * @var ProductCollection|MockObject + */ + private $bundleCollectionMock; + + /** + * @var BundleHelper|MockObject + */ + private $bundleDataMock; + + /** + * @var Selection|MockObject + */ + private $bundleSelectionMock; + + /** + * @var CatalogConfig|MockObject + */ + private $configMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * Object Manager Instance + * + * @var ObjectManager + */ + private $objectManager; + + /** + * Testable Object + * + * @var AppendUpsellProductsObserver + */ + private $observer; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @var ProductLinkCollection|MockObject + */ + private $collectionMock; + + /** + * @var Product|MockObject + */ + private $productMock; + + /** + * @var Visibility|MockObject + */ + private $productVisibilityMock; + + /** + * @inheritdoc + */ + protected function setUp() : void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->createMock(Observer::class); + + $this->bundleCollectionMock = $this->getMockBuilder(ProductCollection::class) + ->disableOriginalConstructor() + ->setMethods([ + 'addAttributeToSelect', + 'addFieldToFilter', + 'addFinalPrice', + 'addMinimalPrice', + 'addStoreFilter', + 'addTaxPercents', + 'load', + 'setFlag', + 'setPageSize', + 'setVisibility' + ]) + ->getMock(); + + $this->bundleDataMock = $this->getMockBuilder(BundleHelper::class) + ->disableOriginalConstructor() + ->setMethods(['getAllowedSelectionTypes']) + ->getMock(); + + $this->bundleSelectionMock = $this->getMockBuilder(Selection::class) + ->disableOriginalConstructor() + ->setMethods(['getParentIdsByChild']) + ->getMock(); + + $this->configMock = $this->getMockBuilder(CatalogConfig::class) + ->disableOriginalConstructor() + ->setMethods(['getProductAttributes']) + ->getMock(); + + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getProduct', 'getCollection', 'getLimit']) + ->getMock(); + + $this->collectionMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['setItems', 'getItems']) + ->getMock(); + + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getCollection', 'getId', 'getTypeId']) + ->getMock(); + + $this->productVisibilityMock = $this->getMockBuilder(Visibility::class) + ->disableOriginalConstructor() + ->setMethods(['getVisibleInCatalogIds']) + ->getMock(); + + $this->observer = $this->objectManager->getObject( + AppendUpsellProductsObserver::class, + [ + 'bundleData' => $this->bundleDataMock, + 'productVisibility' => $this->productVisibilityMock, + 'config' => $this->configMock, + 'bundleSelection' => $this->bundleSelectionMock, + ] + ); + } + + /** + * Test observer execute method + */ + public function testAddBundleCollectionItemsToEventCollection() + { + $collectionItems = [ + 1 => 1 + ]; + $limit = 2; + $parentIds = [1, 3]; + $productId = 2; + $productAttributes = ['attribute1', 'attribute2']; + $visibleInCatalogIds = [10, 11, 12]; + + $this->observerMock + ->expects($this->exactly(3)) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->bundleDataMock + ->expects($this->once()) + ->method('getAllowedSelectionTypes') + ->willReturn($this->getAllowedSelectionTypes()); + + $this->productMock + ->expects($this->once()) + ->method('getTypeId') + ->willReturn(ProductType::TYPE_SIMPLE); + + $this->eventMock + ->expects($this->once()) + ->method('getCollection') + ->willReturn($this->collectionMock); + + $this->eventMock + ->expects($this->once()) + ->method('getLimit') + ->willReturn($limit); + + $this->collectionMock + ->expects($this->exactly(2)) + ->method('getItems') + ->willReturn($collectionItems); + + $this->productMock + ->expects($this->once()) + ->method('getId') + ->willReturn($productId); + + $this->bundleSelectionMock + ->expects($this->once()) + ->method('getParentIdsByChild') + ->willReturn($parentIds); + + $this->productMock + ->expects($this->once()) + ->method('getCollection') + ->willReturn($this->bundleCollectionMock); + + $this->bundleCollectionMock + ->expects($this->once()) + ->method('addAttributeToSelect') + ->willReturn($this->bundleCollectionMock); + + $this->configMock + ->expects($this->once()) + ->method('getProductAttributes') + ->willReturn($productAttributes); + + $this->productVisibilityMock + ->expects($this->once()) + ->method('getVisibleInCatalogIds') + ->willReturn($visibleInCatalogIds); + + $this->bundleCollectionMock + ->expects($this->once()) + ->method('setPageSize') + ->willReturn($this->bundleCollectionMock); + + $this->bundleCollectionMock + ->expects($this->once()) + ->method('addFieldToFilter') + ->willReturn($this->bundleCollectionMock); + + $this->bundleCollectionMock + ->expects($this->once()) + ->method('setFlag') + ->willReturn($this->bundleCollectionMock); + + $this->collectionMock + ->expects($this->once()) + ->method('setItems') + ->willReturn($collectionItems); + + $this->observer->execute($this->observerMock); + } + + /** + * Test observer when collection contains a parent product of a current product + */ + public function testObserverWithoutBundleIds() + { + $collectionItems = [ + 1 => 1 + ]; + $parentIds = [1]; + $limit = 2; + $productId = 2; + + $this->observerMock + ->expects($this->exactly(3)) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->bundleDataMock + ->expects($this->once()) + ->method('getAllowedSelectionTypes') + ->willReturn($this->getAllowedSelectionTypes()); + + $this->productMock + ->expects($this->once()) + ->method('getTypeId') + ->willReturn(ProductType::TYPE_SIMPLE); + + $this->eventMock + ->expects($this->once()) + ->method('getCollection') + ->willReturn($this->collectionMock); + + $this->eventMock + ->expects($this->once()) + ->method('getLimit') + ->willReturn($limit); + + $this->collectionMock + ->expects($this->once()) + ->method('getItems') + ->willReturn($collectionItems); + + $this->productMock + ->expects($this->once()) + ->method('getId') + ->willReturn($productId); + + $this->bundleSelectionMock + ->expects($this->once()) + ->method('getParentIdsByChild') + ->willReturn($parentIds); + + $this->observer->execute($this->observerMock); + } + + /** + * Test observer when count of products is equal to limit. + */ + public function testObserverWithoutLinkedProducts() + { + $collectionItems = [ + 1 => 1 + ]; + $limit = 1; + + $this->observerMock + ->expects($this->exactly(3)) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->bundleDataMock + ->expects($this->once()) + ->method('getAllowedSelectionTypes') + ->willReturn($this->getAllowedSelectionTypes()); + + $this->productMock + ->expects($this->once()) + ->method('getTypeId') + ->willReturn(ProductType::TYPE_SIMPLE); + + $this->eventMock + ->expects($this->once()) + ->method('getCollection') + ->willReturn($this->collectionMock); + + $this->eventMock + ->expects($this->once()) + ->method('getLimit') + ->willReturn($limit); + + $this->collectionMock + ->expects($this->once()) + ->method('getItems') + ->willReturn($collectionItems); + + $this->observer->execute($this->observerMock); + } + + /** + * Test observer when a current product type is allowed for bundle selection + */ + public function testCurrentProductIsNotAllowedForBundleSelection() + { + $this->bundleDataMock + ->expects($this->once()) + ->method('getAllowedSelectionTypes') + ->willReturn($this->getAllowedSelectionTypes()); + + $this->eventMock + ->expects($this->once()) + ->method('getProduct') + ->willReturn($this->productMock); + + $this->observerMock + ->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + + $this->productMock + ->expects($this->once()) + ->method('getTypeId') + ->willReturn(Grouped::TYPE_CODE); + + $this->observer->execute($this->observerMock); + } + + /** + * Returns allowed products types + * + * @return array + */ + private function getAllowedSelectionTypes(): array + { + return [ + 'simple' => ProductType::TYPE_SIMPLE, + 'virtual' => ProductType::TYPE_VIRTUAL, + ]; + } +} From f1fe15394bf74c170f7f2489de7cce9c3c81a1c7 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 17 Jan 2020 18:04:27 +0200 Subject: [PATCH 185/666] MC-30397: Doesn't work: "Files" as fallback when Magento fails to connect to "Redis" --- .../Framework/Session/SaveHandlerTest.php | 148 ++++++++---------- .../Magento/Framework/Session/SaveHandler.php | 87 ++++++---- 2 files changed, 125 insertions(+), 110 deletions(-) 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/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); + } } } From 807b5de95ed8f3ca4b20e398d9db95a2560f2c31 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Fri, 17 Jan 2020 21:30:27 +0200 Subject: [PATCH 186/666] magento/magento2#: Unit test for \Magento\Bundle\Observer\InitOptionRendererObserver --- .../Observer/InitOptionRendererObserver.php | 11 ++- .../InitOptionRendererObserverTest.php | 81 +++++++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Observer/InitOptionRendererObserverTest.php diff --git a/app/code/Magento/Bundle/Observer/InitOptionRendererObserver.php b/app/code/Magento/Bundle/Observer/InitOptionRendererObserver.php index 008ab1d84ac37..377b8a7dea466 100644 --- a/app/code/Magento/Bundle/Observer/InitOptionRendererObserver.php +++ b/app/code/Magento/Bundle/Observer/InitOptionRendererObserver.php @@ -5,20 +5,25 @@ */ namespace Magento\Bundle\Observer; +use Magento\Bundle\Helper\Catalog\Product\Configuration; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; +/** + * Initiates render options + */ class InitOptionRendererObserver implements ObserverInterface { /** * Initialize product options renderer with bundle specific params * - * @param \Magento\Framework\Event\Observer $observer + * @param Observer $observer * @return $this */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { $block = $observer->getBlock(); - $block->addOptionsRenderCfg('bundle', \Magento\Bundle\Helper\Catalog\Product\Configuration::class); + $block->addOptionsRenderCfg('bundle', Configuration::class); return $this; } } diff --git a/app/code/Magento/Bundle/Test/Unit/Observer/InitOptionRendererObserverTest.php b/app/code/Magento/Bundle/Test/Unit/Observer/InitOptionRendererObserverTest.php new file mode 100644 index 0000000000000..78f1d97e888c7 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Observer/InitOptionRendererObserverTest.php @@ -0,0 +1,81 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Bundle\Test\Unit\Observer; + +use Magento\Bundle\Observer\InitOptionRendererObserver; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Wishlist\Block\Customer\Wishlist\Item\Options; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test class for \Magento\Bundle\Observer\InitOptionRendererObserver + */ +class InitOptionRendererObserverTest extends TestCase +{ + /** + * @var Options|MockObject + */ + private $blockMock; + + /** + * Object Manager Instance + * + * @var ObjectManager + */ + private $objectManager; + + /** + * Testable Object + * + * @var InitOptionRendererObserver + */ + private $observer; + + /** + * @var Observer|MockObject + */ + private $observerMock; + + /** + * @inheritdoc + */ + protected function setUp() : void + { + $this->objectManager = new ObjectManager($this); + $this->observerMock = $this->getMockBuilder(Observer::class) + ->disableOriginalConstructor() + ->setMethods(['getBlock']) + ->getMock(); + + $this->blockMock = $this->getMockBuilder(Options::class) + ->disableOriginalConstructor() + ->setMethods(['addOptionsRenderCfg']) + ->getMock(); + + $this->observer = $this->objectManager->getObject(InitOptionRendererObserver::class); + } + + /** + * Test observer execute method + */ + public function testProductOptionRendererInit() + { + $this->observerMock + ->expects($this->once()) + ->method('getBlock') + ->willReturn($this->blockMock); + + $this->blockMock + ->expects($this->once()) + ->method('addOptionsRenderCfg') + ->willReturn($this->blockMock); + + $this->observer->execute($this->observerMock); + } +} From a1959f62e2d73b208e5989e640d6dcb453ef0724 Mon Sep 17 00:00:00 2001 From: Raul E Watson <raul.watson@maginus.com> Date: Fri, 17 Jan 2020 22:34:46 +0000 Subject: [PATCH 187/666] #895 Fix for Media Gallery buttons are shifted to the left --- .../view/adminhtml/web/css/source/_module.less | 13 ------------- .../backend/Magento_Cms/web/css/source/_module.less | 4 ++++ 2 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less diff --git a/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less b/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less deleted file mode 100644 index 4abcfb702a3dd..0000000000000 --- a/app/code/Magento/MediaGallery/view/adminhtml/web/css/source/_module.less +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -.modal-slide { - .media-gallery-modal { - .page-main-actions { - .page-action-buttons{ - text-align: right; - } - } - } -} diff --git a/app/design/adminhtml/Magento/backend/Magento_Cms/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Cms/web/css/source/_module.less index 715ad40dc475f..fda9a1ebdd083 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Cms/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Cms/web/css/source/_module.less @@ -6,6 +6,10 @@ .media-gallery-modal { .page-main-actions { margin-bottom: 3rem; + + .page-action-buttons { + text-align: right; + } } .new_folder { From 3bffb4cc8d16dcb5a4fa5358accd3b3bcedfcd02 Mon Sep 17 00:00:00 2001 From: Vimal Kumar <vimal.kumar@ranosys.com> Date: Sat, 18 Jan 2020 14:17:17 +0530 Subject: [PATCH 188/666] fixed issue #25761 --- .../Sitemap/Model/ItemProvider/StoreUrl.php | 54 ++++++++++++++++ .../ItemProvider/StoreUrlConfigReader.php | 61 +++++++++++++++++++ .../Magento/Sitemap/etc/adminhtml/system.xml | 14 ++++- app/code/Magento/Sitemap/etc/config.xml | 4 ++ app/code/Magento/Sitemap/etc/di.xml | 6 ++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php create mode 100644 app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php new file mode 100644 index 0000000000000..dd7c50385945f --- /dev/null +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sitemap\Model\ItemProvider; + +use Magento\Sitemap\Model\SitemapItemInterfaceFactory; + +class StoreUrl implements ItemProviderInterface +{ + /** + * Sitemap item factory + * + * @var SitemapItemInterfaceFactory + */ + private $itemFactory; + + /** + * Config reader + * + * @var ConfigReaderInterface + */ + private $configReader; + + /** + * CategorySitemapItemResolver constructor. + * + * @param ConfigReaderInterface $configReader + * @param SitemapItemInterfaceFactory $itemFactory + */ + public function __construct( + ConfigReaderInterface $configReader, + SitemapItemInterfaceFactory $itemFactory + ) { + $this->itemFactory = $itemFactory; + $this->configReader = $configReader; + } + + /** + * {@inheritdoc} + */ + public function getItems($storeId) + { + $items[] = $this->itemFactory->create([ + 'url' => '', + 'priority' => $this->configReader->getPriority($storeId), + 'changeFrequency' => $this->configReader->getChangeFrequency($storeId), + ]); + + return $items; + } +} diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php new file mode 100644 index 0000000000000..9a33028d77c76 --- /dev/null +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sitemap\Model\ItemProvider; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; + +class StoreUrlConfigReader implements ConfigReaderInterface +{ + /**#@+ + * Xpath config settings + */ + const XML_PATH_CHANGE_FREQUENCY = 'sitemap/store/changefreq'; + const XML_PATH_PRIORITY = 'sitemap/store/priority'; + /**#@-*/ + + /** + * Scope config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * CategoryItemResolverConfigReader constructor. + * + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct(ScopeConfigInterface $scopeConfig) + { + $this->scopeConfig = $scopeConfig; + } + + /** + * {@inheritdoc} + */ + public function getPriority($storeId) + { + return (string)$this->scopeConfig->getValue( + self::XML_PATH_PRIORITY, + ScopeInterface::SCOPE_STORE, + $storeId + ); + } + + /** + * {@inheritdoc} + */ + public function getChangeFrequency($storeId) + { + return (string)$this->scopeConfig->getValue( + self::XML_PATH_CHANGE_FREQUENCY, + ScopeInterface::SCOPE_STORE, + $storeId + ); + } +} diff --git a/app/code/Magento/Sitemap/etc/adminhtml/system.xml b/app/code/Magento/Sitemap/etc/adminhtml/system.xml index 57c426c68e83f..46ae510287716 100644 --- a/app/code/Magento/Sitemap/etc/adminhtml/system.xml +++ b/app/code/Magento/Sitemap/etc/adminhtml/system.xml @@ -51,7 +51,19 @@ <comment>Valid values range from 0.0 to 1.0.</comment> </field> </group> - <group id="generate" translate="label" type="text" sortOrder="4" showInDefault="1"> + <group id="store" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Store Url Options</label> + <field id="changefreq" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Frequency</label> + <source_model>Magento\Sitemap\Model\Config\Source\Frequency</source_model> + </field> + <field id="priority" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <label>Priority</label> + <backend_model>Magento\Sitemap\Model\Config\Backend\Priority</backend_model> + <comment>Valid values range from 0.0 to 1.0.</comment> + </field> + </group> + <group id="generate" translate="label" type="text" sortOrder="5" showInDefault="1"> <label>Generation Settings</label> <field id="enabled" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Enabled</label> diff --git a/app/code/Magento/Sitemap/etc/config.xml b/app/code/Magento/Sitemap/etc/config.xml index 6f14ff728ac4f..36b2cc2207422 100644 --- a/app/code/Magento/Sitemap/etc/config.xml +++ b/app/code/Magento/Sitemap/etc/config.xml @@ -25,6 +25,10 @@ <changefreq>daily</changefreq> <image_include>all</image_include> </product> + <store> + <priority>1</priority> + <changefreq>daily</changefreq> + </store> <generate> <enabled>0</enabled> <error_email /> diff --git a/app/code/Magento/Sitemap/etc/di.xml b/app/code/Magento/Sitemap/etc/di.xml index e627b3b50fff9..4c4a5f98f737a 100644 --- a/app/code/Magento/Sitemap/etc/di.xml +++ b/app/code/Magento/Sitemap/etc/di.xml @@ -25,12 +25,18 @@ <type name="Magento\Sitemap\Model\ItemProvider\Composite"> <arguments> <argument name="itemProviders" xsi:type="array"> + <item name="storeUrlProvider" xsi:type="object">Magento\Sitemap\Model\ItemProvider\StoreUrl</item> <item name="categoryProvider" xsi:type="object">Magento\Sitemap\Model\ItemProvider\Category</item> <item name="cmsPageProvider" xsi:type="object">Magento\Sitemap\Model\ItemProvider\CmsPage</item> <item name="productProvider" xsi:type="object">Magento\Sitemap\Model\ItemProvider\Product</item> </argument> </arguments> </type> + <type name="Magento\Sitemap\Model\ItemProvider\StoreUrl"> + <arguments> + <argument name="configReader" xsi:type="object">Magento\Sitemap\Model\ItemProvider\StoreUrlConfigReader</argument> + </arguments> + </type> <type name="Magento\Sitemap\Model\ItemProvider\Category"> <arguments> <argument name="configReader" xsi:type="object">Magento\Sitemap\Model\ItemProvider\CategoryConfigReader</argument> From a39bc8c5dad9baedc1ca9031e38eb507c4cd143b Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Sat, 18 Jan 2020 12:29:47 +0100 Subject: [PATCH 189/666] Add frontend template hints status command --- .../Command/TemplateHintsShowCommand.php | 66 +++++++++++++++++++ app/code/Magento/Developer/etc/di.xml | 1 + 2 files changed, 67 insertions(+) create mode 100644 app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php new file mode 100644 index 0000000000000..55ffaee646abb --- /dev/null +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Developer\Console\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\App\Config\ConfigResource\ConfigInterface; + +class TemplateHintsShowCommand extends Command +{ + + /** + * command name + */ + const COMMAND_NAME = 'dev:template-hints:show'; + + /** + * Success message + */ + const SUCCESS_MESSAGE = "Template hints are "; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * Initialize dependencies. + * + * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + */ + public function __construct( + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + ) + { + parent::__construct(); + $this->scopeConfig = $scopeConfig; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName(self::COMMAND_NAME) + ->setDescription('Show frontend template hints status.'); + + parent::configure(); + } + + /** + * {@inheritdoc} + * @throws \InvalidArgumentException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $templateHintsStatus = ($this->scopeConfig->getValue('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; + $templateHintsMessage = self::SUCCESS_MESSAGE . $templateHintsStatus; + $output->writeln("<info>". $templateHintsMessage . "</info>"); + } +} diff --git a/app/code/Magento/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index d8f8eb6c1221e..c2a845d1b794f 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -105,6 +105,7 @@ <item name="dev_query_log_disable" xsi:type="object">Magento\Developer\Console\Command\QueryLogDisableCommand</item> <item name="dev_template_hints_disable" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsDisableCommand</item> <item name="dev_template_hints_enable" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsEnableCommand</item> + <item name="dev_template_hints_show" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsShowCommand</item> <item name="dev_profiler_disable" xsi:type="object">Magento\Developer\Console\Command\ProfilerDisableCommand</item> <item name="dev_profiler_enable" xsi:type="object">Magento\Developer\Console\Command\ProfilerEnableCommand</item> <item name="dev_generate_patch" xsi:type="object">Magento\Developer\Console\Command\GeneratePatchCommand</item> From f37c228d50c93ef21f4d477ccdb1f59c874867c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sat, 18 Jan 2020 17:17:46 +0100 Subject: [PATCH 190/666] Added Unit Tests for 2 cases and introduce fallback ( [[]] ) --- .../Block/Product/ProductList/Upsell.php | 2 +- .../Block/Product/ProductList/UpsellTest.php | 40 +++++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php index cf7e992650e1f..3c3a78201dddc 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php @@ -269,7 +269,7 @@ public function getIdentities() { $identities = array_map(function (DataObject $item) { return $item->getIdentities(); - }, $this->getItems()); + }, $this->getItems()) ?: [[]]; return array_merge(...$identities); } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/UpsellTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/UpsellTest.php index 03f3c83d87dcb..f3aa3f182d198 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/UpsellTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ProductList/UpsellTest.php @@ -5,17 +5,21 @@ */ namespace Magento\Catalog\Test\Unit\Block\Product\ProductList; +use Magento\Catalog\Block\Product\ProductList\Upsell as UpsellBlock; +use Magento\Catalog\Model\Product; + class UpsellTest extends \PHPUnit\Framework\TestCase { + const STUB_EMPTY_ARRAY = []; /** - * @var \Magento\Catalog\Block\Product\ProductList\Upsell + * @var UpsellBlock */ protected $block; protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->block = $objectManager->getObject(\Magento\Catalog\Block\Product\ProductList\Upsell::class); + $this->block = $objectManager->getObject(UpsellBlock::class); } protected function tearDown() @@ -26,10 +30,10 @@ protected function tearDown() public function testGetIdentities() { $productTag = ['compare_item_1']; - $product = $this->createMock(\Magento\Catalog\Model\Product::class); + $product = $this->createMock(Product::class); $product->expects($this->once())->method('getIdentities')->will($this->returnValue($productTag)); - $itemsCollection = new \ReflectionProperty(\Magento\Catalog\Block\Product\ProductList\Upsell::class, '_items'); + $itemsCollection = new \ReflectionProperty(UpsellBlock::class, '_items'); $itemsCollection->setAccessible(true); $itemsCollection->setValue($this->block, [$product]); @@ -38,4 +42,32 @@ public function testGetIdentities() $this->block->getIdentities() ); } + + public function testGetIdentitiesWhenItemGetIdentitiesReturnEmptyArray() + { + $product = $this->createMock(Product::class); + $product->expects($this->once())->method('getIdentities') + ->willReturn(self::STUB_EMPTY_ARRAY); + + $itemsCollection = new \ReflectionProperty(UpsellBlock::class, '_items'); + $itemsCollection->setAccessible(true); + $itemsCollection->setValue($this->block, [$product]); + + $this->assertEquals( + self::STUB_EMPTY_ARRAY, + $this->block->getIdentities() + ); + } + + public function testGetIdentitiesWhenGetItemsReturnEmptyArray() + { + $itemsCollection = new \ReflectionProperty(UpsellBlock::class, '_items'); + $itemsCollection->setAccessible(true); + $itemsCollection->setValue($this->block, self::STUB_EMPTY_ARRAY); + + $this->assertEquals( + self::STUB_EMPTY_ARRAY, + $this->block->getIdentities() + ); + } } From 390b919018740722a37e89f723078faa4ccf40cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Sat, 18 Jan 2020 17:45:48 +0100 Subject: [PATCH 191/666] Add description --- .../Test/Unit/Plugin/DisableMultishippingModeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php index 25a095381333e..829d5a9ce2763 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php @@ -16,7 +16,7 @@ use Magento\Quote\Model\Quote; /** - * Class DisableMultishippingModeTest + * Set of Unit Tets to cover DisableMultishippingMode */ class DisableMultishippingModeTest extends \PHPUnit\Framework\TestCase { From 57b8f53c447a8b07f521a677678921364891b3b6 Mon Sep 17 00:00:00 2001 From: Deepak S Nair <deepak.nair@ranosys.com> Date: Mon, 20 Jan 2020 10:25:01 +0530 Subject: [PATCH 192/666] update sort order --- app/code/Magento/Sitemap/etc/adminhtml/system.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sitemap/etc/adminhtml/system.xml b/app/code/Magento/Sitemap/etc/adminhtml/system.xml index 46ae510287716..8814d7dcf67bd 100644 --- a/app/code/Magento/Sitemap/etc/adminhtml/system.xml +++ b/app/code/Magento/Sitemap/etc/adminhtml/system.xml @@ -53,11 +53,11 @@ </group> <group id="store" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Store Url Options</label> - <field id="changefreq" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <field id="changefreq" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Frequency</label> <source_model>Magento\Sitemap\Model\Config\Source\Frequency</source_model> </field> - <field id="priority" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <field id="priority" translate="label comment" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Priority</label> <backend_model>Magento\Sitemap\Model\Config\Backend\Priority</backend_model> <comment>Valid values range from 0.0 to 1.0.</comment> @@ -106,7 +106,7 @@ </depends> </field> </group> - <group id="limit" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="limit" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Sitemap File Limits</label> <field id="max_lines" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Maximum No of URLs Per File</label> @@ -118,7 +118,7 @@ <validate>validate-number validate-greater-than-zero</validate> </field> </group> - <group id="search_engines" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="search_engines" translate="label" type="text" sortOrder="7" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Search Engine Submission Settings</label> <field id="submission_robots" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Enable Submission to Robots.txt</label> From 3a19f179309633f3c12ee8e039e5dd5b2d513624 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Mon, 20 Jan 2020 09:35:50 +0200 Subject: [PATCH 193/666] #18012: updated JS config 'i18n_translation' pattern in order to add _.i18n --- app/code/Magento/Translation/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Translation/etc/di.xml b/app/code/Magento/Translation/etc/di.xml index d17dac23933ee..de476f52a53fe 100644 --- a/app/code/Magento/Translation/etc/di.xml +++ b/app/code/Magento/Translation/etc/di.xml @@ -64,7 +64,7 @@ <type name="Magento\Translation\Model\Js\Config"> <arguments> <argument name="patterns" xsi:type="array"> - <item name="i18n_translation" xsi:type="string"><![CDATA[~i18n\:\s*(["'])(.*?)(?<!\\)\1~]]></item> + <item name="i18n_translation" xsi:type="string"><![CDATA[~(?:i18n\:|_\.i18n\()\s*(["'])(.*?)(?<!\\)\1~]]></item> <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> From 7633af187af63892ce58ed89b199a9bbf7e8a590 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 20 Jan 2020 09:52:51 +0200 Subject: [PATCH 194/666] MC-30398: Filter are not present on category page --- .../Data/UpdateDefaultAttributeValue.php | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php index 1d58de1994a11..e658d837efbaf 100644 --- a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php @@ -3,19 +3,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Catalog\Setup\Patch\Data; use Magento\Catalog\Setup\CategorySetup; use Magento\Catalog\Setup\CategorySetupFactory; -use Magento\Framework\App\ResourceConnection; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Setup\Patch\DataPatchInterface; use Magento\Framework\Setup\Patch\PatchVersionInterface; /** - * Class UpdateDefaultAttributeValue - * @package Magento\Catalog\Setup\Patch + * Updates 'is_anchor' attribute default value. */ class UpdateDefaultAttributeValue implements DataPatchInterface, PatchVersionInterface { @@ -30,7 +29,6 @@ class UpdateDefaultAttributeValue implements DataPatchInterface, PatchVersionInt private $categorySetupFactory; /** - * PatchInitial constructor. * @param ModuleDataSetupInterface $moduleDataSetup * @param CategorySetupFactory $categorySetupFactory */ @@ -43,17 +41,22 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function apply() { /** @var CategorySetup $categorySetup */ $categorySetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); - $categorySetup->updateAttribute(3, 54, 'default_value', 1); + $categorySetup->updateAttribute( + CategorySetup::CATEGORY_ENTITY_TYPE_ID, + 'is_anchor', + 'default_value', + 1 + ); } /** - * {@inheritdoc} + * @inheritdoc */ public static function getDependencies() { @@ -63,7 +66,7 @@ public static function getDependencies() } /** - * {@inheritdoc} + * @inheritdoc */ public static function getVersion() { @@ -71,7 +74,7 @@ public static function getVersion() } /** - * {@inheritdoc} + * @inheritdoc */ public function getAliases() { From 8d1102571a8631fcef97f4896101e7b12f52f51d Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 20 Jan 2020 10:16:58 +0200 Subject: [PATCH 195/666] MC-24256: [Integration Test] Export Customers Main File with multiple websites --- .../import_export/customers_with_websites.php | 18 ++++++++++++++++++ .../customers_with_websites_rollback.php | 9 +++++++++ .../Model/Export/CustomerTest.php | 14 ++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php new file mode 100644 index 0000000000000..3ee6530063dbd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Customer\Api\CustomerRepositoryInterface; + +require __DIR__ . '/customers.php'; +require __DIR__ . '/../../../Store/_files/website.php'; + +$objectManager = Bootstrap::getObjectManager(); +$repository = $objectManager->create(CustomerRepositoryInterface::class); +$customer = $repository->get('customer@example.com'); +$customer->setWebsiteId($website->getId()); +$repository->save($customer); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php new file mode 100644 index 0000000000000..09858172126f5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/import_export/customers_with_websites_rollback.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +include __DIR__ . '/customers_rollback.php'; +include __DIR__ . '/../../../Store/_files/website_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php index 884a4a38ebe0f..9a178aafb0aee 100644 --- a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php +++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Export/CustomerTest.php @@ -75,6 +75,20 @@ public function testExport() $this->checkExportData($lines, $expectedAttributes); } + /** + * Export with Multi Websites "Customer Main File". + * + * @magentoDataFixture Magento/Customer/_files/import_export/customers_with_websites.php + * @return void + */ + public function testExportWithMultiWebsites(): void + { + $this->processCustomerAttribute(); + $expectedAttributes = $this->getExpectedAttributes(); + $lines = $this->export($expectedAttributes); + $this->checkExportData($lines, $expectedAttributes); + } + /** * Return attributes which should be exported. * From 690f791cc76e435d15da1c3eb5f8a4e4f63200ea Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Mon, 20 Jan 2020 10:29:42 +0200 Subject: [PATCH 196/666] 25162 fixed wrong format link --- .../Newsletter/Controller/Subscriber/NewAction.php | 4 +++- app/code/Magento/Newsletter/etc/frontend/di.xml | 12 ++++++++++++ .../messages/localizedSubscriptionErrorMessage.phtml | 9 +++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Newsletter/view/frontend/templates/messages/localizedSubscriptionErrorMessage.phtml diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php b/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php index ea52ae8aaa864..0944ea4626586 100644 --- a/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php +++ b/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php @@ -172,7 +172,9 @@ public function execute() $message = $this->getSuccessMessage((int)$subscriber->getSubscriberStatus()); $this->messageManager->addSuccessMessage($message); } catch (LocalizedException $e) { - $this->messageManager->addErrorMessage($e->getMessage()); + $this->messageManager->addComplexErrorMessage( + 'localizedSubscriptionErrorMessage', ['message' => $e->getMessage()] + ); } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, __('Something went wrong with the subscription.')); } diff --git a/app/code/Magento/Newsletter/etc/frontend/di.xml b/app/code/Magento/Newsletter/etc/frontend/di.xml index eef123a3304e3..99e90faff4034 100644 --- a/app/code/Magento/Newsletter/etc/frontend/di.xml +++ b/app/code/Magento/Newsletter/etc/frontend/di.xml @@ -13,4 +13,16 @@ </argument> </arguments> </type> + <type name="Magento\Framework\View\Element\Message\MessageConfigurationsPool"> + <arguments> + <argument name="configurationsMap" xsi:type="array"> + <item name="localizedSubscriptionErrorMessage" xsi:type="array"> + <item name="renderer" xsi:type="const">\Magento\Framework\View\Element\Message\Renderer\BlockRenderer::CODE</item> + <item name="data" xsi:type="array"> + <item name="template" xsi:type="string">Magento_Newsletter::messages/localizedSubscriptionErrorMessage.phtml</item> + </item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Newsletter/view/frontend/templates/messages/localizedSubscriptionErrorMessage.phtml b/app/code/Magento/Newsletter/view/frontend/templates/messages/localizedSubscriptionErrorMessage.phtml new file mode 100644 index 0000000000000..46c35002e3995 --- /dev/null +++ b/app/code/Magento/Newsletter/view/frontend/templates/messages/localizedSubscriptionErrorMessage.phtml @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/** @var \Magento\Framework\View\Element\Template $block */ +?> +<?= $block->escapeHtml(__($block->getData('message')), ['a']); ?> From 914bae6e0f1fefb974c47694aba0032ad9d3e2a2 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Mon, 20 Jan 2020 10:44:06 +0200 Subject: [PATCH 197/666] MC-30398: Filter are not present on category page --- .../Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php index e658d837efbaf..4500d86ad4a6c 100644 --- a/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php +++ b/app/code/Magento/Catalog/Setup/Patch/Data/UpdateDefaultAttributeValue.php @@ -53,6 +53,8 @@ public function apply() 'default_value', 1 ); + + return $this; } /** From f4a46e7ea6278ddc0c1779d231287844445a75b3 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Mon, 20 Jan 2020 09:45:09 +0100 Subject: [PATCH 198/666] Add frontend template hints status command after suggestions --- ...owCommand.php => TemplateHintsStatusCommand.php} | 13 ++++++------- app/code/Magento/Developer/etc/di.xml | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) rename app/code/Magento/Developer/Console/Command/{TemplateHintsShowCommand.php => TemplateHintsStatusCommand.php} (73%) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php similarity index 73% rename from app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php rename to app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 55ffaee646abb..81df48d6df49f 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsShowCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -9,20 +9,19 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Magento\Framework\App\Config\ConfigResource\ConfigInterface; -class TemplateHintsShowCommand extends Command +class TemplateHintsStatusCommand extends Command { /** * command name */ - const COMMAND_NAME = 'dev:template-hints:show'; + const COMMAND_NAME = 'dev:template-hints:status'; /** * Success message */ - const SUCCESS_MESSAGE = "Template hints are "; + const SUCCESS_MESSAGE = "Template hints are %status"; /** * @var \Magento\Framework\App\Config\ScopeConfigInterface @@ -54,13 +53,13 @@ protected function configure() } /** - * {@inheritdoc} + * @inheritdoc * @throws \InvalidArgumentException */ protected function execute(InputInterface $input, OutputInterface $output) { - $templateHintsStatus = ($this->scopeConfig->getValue('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; - $templateHintsMessage = self::SUCCESS_MESSAGE . $templateHintsStatus; + $templateHintsStatus = ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; + $templateHintsMessage = __(self::SUCCESS_MESSAGE, ['status' => $templateHintsStatus]); $output->writeln("<info>". $templateHintsMessage . "</info>"); } } diff --git a/app/code/Magento/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index c2a845d1b794f..3e08466c6a001 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -105,7 +105,7 @@ <item name="dev_query_log_disable" xsi:type="object">Magento\Developer\Console\Command\QueryLogDisableCommand</item> <item name="dev_template_hints_disable" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsDisableCommand</item> <item name="dev_template_hints_enable" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsEnableCommand</item> - <item name="dev_template_hints_show" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsShowCommand</item> + <item name="dev_template_hints_status" xsi:type="object">Magento\Developer\Console\Command\TemplateHintsStatusCommand</item> <item name="dev_profiler_disable" xsi:type="object">Magento\Developer\Console\Command\ProfilerDisableCommand</item> <item name="dev_profiler_enable" xsi:type="object">Magento\Developer\Console\Command\ProfilerEnableCommand</item> <item name="dev_generate_patch" xsi:type="object">Magento\Developer\Console\Command\GeneratePatchCommand</item> From 141ca96b1ac0973ac1c46f8a225f4e69291c01fd Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Mon, 20 Jan 2020 11:17:31 +0200 Subject: [PATCH 199/666] 25162 added MFTF tests --- ...rConfigFieldGuestNotAllowedActionGroup.xml | 18 +++++++++++++ .../Mftf/Page/AdminNewsletterConfigPage.xml | 13 ++++++++++ ...erConfigPageSubscriptionOptionsSection.xml | 14 ++++++++++ .../Section/NewsletterTemplateSection.xml | 4 +++ ...inkDisplayedForGuestSubscriptionNoTest.xml | 26 +++++++++++++++++++ 5 files changed, 75 insertions(+) create mode 100644 app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Page/AdminNewsletterConfigPage.xml create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml new file mode 100644 index 0000000000000..73fb9de740ba7 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.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="AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup"> + <amOnPage url="{{AdminNewsletterConfigPage.url}}" stepKey="amOnNewsletterConfigPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <click selector="{{AdminNewsletterConfigPageSubscriptionOptionsSection.allowGuestSubscription}}" stepKey="allowEdit"/> + <selectOption selector="{{AdminNewsletterConfigPageSubscriptionOptionsSection.guestSubscription}}" userInput="No" stepKey="noGuestSubscription"/> + <click selector="{{AdminMainActionsSection.save}}" stepKey="saveNewsletterConfig"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Page/AdminNewsletterConfigPage.xml b/app/code/Magento/Newsletter/Test/Mftf/Page/AdminNewsletterConfigPage.xml new file mode 100644 index 0000000000000..00cbaa1656326 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Page/AdminNewsletterConfigPage.xml @@ -0,0 +1,13 @@ +<?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="AdminNewsletterConfigPage" url="admin/system_config/edit/section/newsletter/" area="admin" module="Magento_Newsletter"> + <section name="AdminNewsletterConfigPageSubscriptionOptionsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml new file mode 100644 index 0000000000000..26fdcf10ede02 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml @@ -0,0 +1,14 @@ +<?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="AdminNewsletterConfigPageSubscriptionOptionsSection"> + <element name="allowGuestSubscription" type="input" selector="#newsletter_subscription_allow_guest_subscribe_inherit"/> + <element name="guestSubscription" type="select" selector="#newsletter_subscription_allow_guest_subscribe" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml index 4c8f641f78ae3..ebc1577fd5ece 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml @@ -7,6 +7,10 @@ --> <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="BasicFrontendNewsletterFormSection"> + <element name="newsletterEmail" type="input" selector="#newsletter"/> + <element name="subscribeButton" type="button" selector=".subscribe"/> + </section> <section name="BasicFieldNewsletterSection"> <element name="templateName" type="input" selector="#code"/> <element name="templateSubject" type="input" selector="#subject"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml new file mode 100644 index 0000000000000..b5cb4e2fa62bc --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml @@ -0,0 +1,26 @@ +<?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="VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest"> + <before> + <!--Log in to Magento as admin.--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Allow Guest Subscription NO--> + <actionGroup ref="AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup" stepKey="amOnNewsletterConfigField"/> + <!--Log out from Magento admin.--> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + </before> + + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <fillField selector="{{BasicFrontendNewsletterFormSection.newsletterEmail}}" userInput="{{_defaultNewsletter.senderEmail}}" stepKey="fillTemplateEmail" /> + <click selector="{{BasicFrontendNewsletterFormSection.subscribeButton}}" stepKey="subscribe"/> + <waitForElement selector=".messages" stepKey="waitMessage"/> + </test> +</tests> From f060ee7d46a5a88b97c846c1c37fd3d3c447c32d Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Mon, 20 Jan 2020 12:18:10 +0200 Subject: [PATCH 200/666] fixed code style issue --- .../Magento/Newsletter/Controller/Subscriber/NewAction.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php b/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php index 0944ea4626586..c27a4db926d06 100644 --- a/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php +++ b/app/code/Magento/Newsletter/Controller/Subscriber/NewAction.php @@ -173,7 +173,8 @@ public function execute() $this->messageManager->addSuccessMessage($message); } catch (LocalizedException $e) { $this->messageManager->addComplexErrorMessage( - 'localizedSubscriptionErrorMessage', ['message' => $e->getMessage()] + 'localizedSubscriptionErrorMessage', + ['message' => $e->getMessage()] ); } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, __('Something went wrong with the subscription.')); From a1212509c813239ef8ab0236d623414831bbac12 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 20 Jan 2020 12:37:34 +0200 Subject: [PATCH 201/666] cover changes with jasmine test --- .../Magento/Ui/base/js/modal/modal.test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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..ddf9c82bd1886 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,34 @@ define([ 'use strict'; describe('ui/js/modal/modal', function () { - var element = $('<div>some element</div>'), + + var element = $('<div>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>'); + 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 stTitle() method set title', function () { + var newTitle = 'New modal title'; + + modal.setTitle(newTitle); + expect($(modal.options.modalTitle).text()).toBe(newTitle); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); + }); }); }); From a4aa69b8e0a2343a8966c7fc243f68bf3b576ecc Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Mon, 20 Jan 2020 11:39:48 +0100 Subject: [PATCH 202/666] Add frontend template hints status command after suggestions --- .../Console/Command/TemplateHintsStatusCommand.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 81df48d6df49f..d9af42ee33cb4 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -9,6 +9,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; class TemplateHintsStatusCommand extends Command { @@ -24,25 +25,23 @@ class TemplateHintsStatusCommand extends Command const SUCCESS_MESSAGE = "Template hints are %status"; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ protected $scopeConfig; /** * Initialize dependencies. * - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param ScopeConfigInterface $scopeConfig */ - public function __construct( - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - ) + public function __construct(ScopeConfigInterface $scopeConfig) { parent::__construct(); $this->scopeConfig = $scopeConfig; } /** - * {@inheritdoc} + * @inheritdoc */ protected function configure() { @@ -60,6 +59,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { $templateHintsStatus = ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; $templateHintsMessage = __(self::SUCCESS_MESSAGE, ['status' => $templateHintsStatus]); - $output->writeln("<info>". $templateHintsMessage . "</info>"); + $output->writeln("<info>" . $templateHintsMessage . "</info>"); } } From fcce5b8592f884bec431767d903150137a1a6c6e Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 20 Jan 2020 13:03:54 +0200 Subject: [PATCH 203/666] fix typo --- .../tests/app/code/Magento/Ui/base/js/modal/modal.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 ddf9c82bd1886..ccfad86c6cfb0 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 @@ -32,12 +32,12 @@ define([ expect($(modal).length).toEqual(1); }); - it('Verify stTitle() method set title', function () { + it('Verify setTitle() method set title', function () { var newTitle = 'New modal title'; modal.setTitle(newTitle); - expect($(modal.options.modalTitle).text()).toBe(newTitle); - expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); + expect($(modal.options.modalTitle).text()).toContain(newTitle); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(2); }); }); }); From c32b64377fc06771f12e74b4add2f32c8fa0a555 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Mon, 20 Jan 2020 14:32:56 +0200 Subject: [PATCH 204/666] #18012: added description for _.i18n --- lib/web/mage/translate.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/translate.js b/lib/web/mage/translate.js index b96586ab9e927..0a385da8dcf38 100644 --- a/lib/web/mage/translate.js +++ b/lib/web/mage/translate.js @@ -49,8 +49,14 @@ define([ // Provide i18n wrapper to be used in underscore templates for translation _.extend(_, { - i18n: function (str) { - return $.mage.__(str); + /** + * Make a translation using $.mage.__ + * + * @param {String} text + * @return {String} + */ + i18n: function (text) { + return $.mage.__(text); } }); From e99457737d2e028fc8206056ea1f464f4278ad21 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Mon, 20 Jan 2020 15:36:18 +0200 Subject: [PATCH 205/666] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/SearchEntityResultsTest.xml | 97 ------------------- 1 file changed, 97 deletions(-) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index c289fc7868a10..7648b59aaefe8 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -603,101 +603,4 @@ <argument name="value" value="$simpleProduct1.name$"/> </actionGroup> </test> - - <test name="QuickSearchConfigurableChildren"> - <annotations> - <stories value="Search Product on Storefront"/> - <title value="Deprecated. User should be able to use Quick Search to a configurable product's child products"/> - <description value="Use Quick Search to find a configurable product with enabled/disable children"/> - <severity value="MAJOR"/> - <testCaseId value="MC-14798"/> - <group value="CatalogSearch"/> - <group value="mtf_migrated"/> - <skip> - <issueId value="DEPRECATED">Use StorefrontQuickSearchConfigurableChildrenTest instead.</issueId> - </skip> - </annotations> - <before> - <!-- Create the category --> - <createData entity="ApiCategory" stepKey="createCategory"/> - - <!-- Create blank AttributeSet--> - <createData entity="CatalogAttributeSet" stepKey="attributeSet"/> - - <!-- Create an attribute with two options to be used in the first child product --> - <createData entity="hiddenDropdownAttributeWithOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Assign attribute to set --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <actionGroup ref="goToAttributeGridPage" stepKey="goToPage"/> - <actionGroup ref="GoToAttributeSetByNameActionGroup" stepKey="goToSet"> - <argument name="name" value="$attributeSet.attribute_set_name$"/> - </actionGroup> - <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignToAttributeSetAndGroup"> - <argument name="group" value="Product Details"/> - <argument name="attribute" value="$createConfigProductAttribute.attribute_code$"/> - </actionGroup> - <actionGroup ref="SaveAttributeSetActionGroup" stepKey="savePage"/> - - <!-- Get the first option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Create a simple product,give it the attributeSet and attribute with the first option --> - <createData entity="ApiSimpleOneHidden" stepKey="createConfigChildProduct1"> - <field key="attribute_set_id">$attributeSet.attribute_set_id$</field> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - <updateData entity="ApiSimpleProductUpdateDescription" stepKey="updateSimpleProduct1" createDataKey="createConfigChildProduct1"/> - - <!-- Create the configurable product, give it the attributeSet and add it to the category --> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> - <field key="attribute_set_id">$attributeSet.attribute_set_id$</field> - <requiredEntity createDataKey="createCategory"/> - </createData> - <!-- Create the configurable product --> - <createData entity="ConfigurableProductOneOption" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - <!-- Add the first simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct1"/> - </createData> - - <!-- Perform reindex and flush cache --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> - </before> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> - <argument name="phrase" value="$createConfigProduct.name$"/> - </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameInGridActionGroup" stepKey="seeProductInGrid"> - <argument name="productName" value="$createConfigProduct.name$"/> - <argument name="index" value="1"/> - </actionGroup> - - <!-- Disable Child Product --> - <actionGroup ref="GoToProductPageViaIDActionGroup" stepKey="goToChildProduct"> - <argument name="productId" value="$createConfigChildProduct1.id$"/> - </actionGroup> - <actionGroup ref="ToggleProductEnabledActionGroup" stepKey="disableProduct"/> - <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPageAgain"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefrontAgain"> - <argument name="phrase" value="$createConfigProduct.name$"/> - </actionGroup> - <actionGroup ref="StorefrontQuickSearchCheckProductNameNotInGridActionGroup" stepKey="dontSeeProductAnymore"> - <argument name="productName" value="$createConfigProduct.name$"/> - </actionGroup> - </test> </tests> From 1044f254a4fbc24342ecb6127d2eb484533e6fc3 Mon Sep 17 00:00:00 2001 From: Erfan Shamabadi <erfan@codekunst.com> Date: Mon, 20 Jan 2020 14:48:59 +0100 Subject: [PATCH 206/666] Escape dollar sign for saving content into crontab The crontab contents can contain dollar sign (e.g. $(date)). The current code does not escape it which transform it to actual values. In this commit a replacement to escape dollar sign is added to the previous replacements. --- lib/internal/Magento/Framework/Crontab/CrontabManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManager.php b/lib/internal/Magento/Framework/Crontab/CrontabManager.php index fb3537ca0648f..a6496e4d01c04 100644 --- a/lib/internal/Magento/Framework/Crontab/CrontabManager.php +++ b/lib/internal/Magento/Framework/Crontab/CrontabManager.php @@ -203,7 +203,7 @@ private function getCrontabContent() */ private function save($content) { - $content = str_replace(['%', '"'], ['%%', '\"'], $content); + $content = str_replace(['%', '"', '$'], ['%%', '\"', '\$'], $content); try { $this->shell->execute('echo "' . $content . '" | crontab -'); From f309ae042236736db0a964e533e33baa0a0e5142 Mon Sep 17 00:00:00 2001 From: kalinicham <Hvdygfijf13795> Date: Mon, 20 Jan 2020 15:54:16 +0200 Subject: [PATCH 207/666] Cover changes with Unit test --- .../Backend/TierPrice/UpdateHandlerTest.php | 145 ++++++++++++++---- 1 file changed, 116 insertions(+), 29 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php index 88adec0e20376..8b398d3ba4d97 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php @@ -7,13 +7,13 @@ namespace Magento\Catalog\Test\Unit\Model\Attribute\Backend\TierPrice; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\UpdateHandler; -use Magento\Store\Model\StoreManagerInterface; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\UpdateHandler; +use Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice; use Magento\Customer\Api\GroupManagementInterface; use Magento\Framework\EntityManager\MetadataPool; -use Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\StoreManagerInterface; /** * Unit tests for \Magento\Catalog\Model\Product\Attribute\Backend\TierPrice\UpdateHandler @@ -95,20 +95,27 @@ protected function setUp() ); } - public function testExecute(): void - { - $newTierPrices = [ - ['website_id' => 0, 'price_qty' => 2, 'cust_group' => 0, 'price' => 15], - ['website_id' => 0, 'price_qty' => 3, 'cust_group' => 3200, 'price' => null, 'percentage_value' => 20] - ]; - $priceIdToDelete = 2; - $originalTierPrices = [ - ['price_id' => 1, 'website_id' => 0, 'price_qty' => 2, 'cust_group' => 0, 'price' => 10], - ['price_id' => $priceIdToDelete, 'website_id' => 0, 'price_qty' => 4, 'cust_group' => 0, 'price' => 20], - ]; - $linkField = 'entity_id'; - $productId = 10; - $originalProductId = 11; + /** + * Verify update handle. + * + * @param array $newTierPrices + * @param array $originalTierPrices + * @param int $priceIdToDelete + * @param string $linkField + * @param int $productId + * @param int $originalProductId + * @throws \Magento\Framework\Exception\InputException + * + * @dataProvider configDataProvider + */ + public function testExecute( + $newTierPrices, + $originalTierPrices, + $priceIdToDelete, + $linkField, + $productId, + $originalProductId + ): void { /** @var \PHPUnit_Framework_MockObject_MockObject $product */ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class) @@ -128,18 +135,12 @@ public function testExecute(): void ['entity_id', $originalProductId] ] ); - $this->assertEquals( - $this->assertNotNull($newTierPrices[0]['price']), - $this->tierPriceResource->expects($this->atLeastOnce()) - ->method('updateValues')->with($newTierPrices, $originalTierPrices)->willReturn(true) - ); - $this->assertEquals( - $this->assertNull($newTierPrices[0]['price']), - $this->tierPriceResource->expects($this->atLeastOnce()) - ->method('updateValues')->with($newTierPrices, $originalTierPrices)->willReturn(false) - ); + $product->expects($this->atLeastOnce())->method('getStoreId')->willReturn(0); - $product->expects($this->atLeastOnce())->method('setData')->with('tier_price_changed', 1); + + $product->expects($this->atLeastOnce()) + ->method('setData') + ->with('tier_price_changed', 1); $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) ->disableOriginalConstructor() ->setMethods(['getWebsiteId']) @@ -177,6 +178,8 @@ public function testExecute(): void } /** + * Verify update handle with exception. + * * @expectedException \Magento\Framework\Exception\InputException * @expectedExceptionMessage Tier prices data should be array, but actually other type is received */ @@ -199,4 +202,88 @@ public function testExecuteWithException(): void $this->updateHandler->execute($product); } + + /** + * Returns test parameters. + * + * @return array + */ + public function configDataProvider() + { + return [ + [ + [ + [ + 'website_id' => 0, + 'price_qty' => 2, + 'cust_group' => 0, + 'price' => 15 + ], + [ + 'website_id' => 0, + 'price_qty' => 3, + 'cust_group' => 3200, + 'price' => null, + 'percentage_value' => 20 + ] + ], + [ + [ + 'price_id' => 1, + 'website_id' => 0, + 'price_qty' => 2, + 'cust_group' => 0, + 'price' => 10], + [ + 'price_id' => 2, + 'website_id' => 0, + 'price_qty' => 4, + 'cust_group' => 0, + 'price' => 20 + ], + ], + 2, + 'entity_id', + 10, + 11 + ], + [ + [ + [ + 'website_id' => 0, + 'price_qty' => 2, + 'cust_group' => 0, + 'price' => 0 + ], + [ + 'website_id' => 0, + 'price_qty' => 3, + 'cust_group' => 3200, + 'price' => null, + 'percentage_value' => 20 + ] + ], + [ + [ + 'price_id' => 1, + 'website_id' => 0, + 'price_qty' => 2, + 'cust_group' => 0, + 'price' => 10 + ], + [ + 'price_id' => 2, + 'website_id' => 0, + 'price_qty' => 4, + 'cust_group' => 0, + 'price' => 20 + ], + ], + 2, + 'entity_id', + 10, + 11 + ] + ]; + } } From 093e30600f58f506a3dc5e853b8b3c4b205157f4 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 20 Jan 2020 17:16:30 +0200 Subject: [PATCH 208/666] MC-24906: An error notification is displayed while creating return on storefront --- .../shipment_for_order_with_customer.php | 27 +++++++++++++++++++ ...pment_for_order_with_customer_rollback.php | 8 ++++++ 2 files changed, 35 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer.php b/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer.php new file mode 100644 index 0000000000000..c5304f5b8809f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\DB\Transaction; +use Magento\Sales\Model\Order\ShipmentFactory; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/order_with_customer.php'; + +$objectManager = Bootstrap::getObjectManager(); +$order->setIsInProcess(true); +/** @var Transaction $transaction */ +$transaction = $objectManager->create(Transaction::class); + +$items = []; +foreach ($order->getItems() as $orderItem) { + $items[$orderItem->getId()] = $orderItem->getQtyOrdered(); +} + +$shipment = $objectManager->get(ShipmentFactory::class)->create($order, $items); +$shipment->register(); + +$transaction->addObject($shipment)->addObject($order)->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_customer_rollback.php new file mode 100644 index 0000000000000..2595d6bf4084a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/shipment_for_order_with_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__ . '/default_rollback.php'; From bdb46793b5aab8ed78bee5196538c7dfb229bc0e Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Tue, 21 Jan 2020 09:16:57 +0100 Subject: [PATCH 209/666] Add frontend template hints status command after suggestions --- .../Console/Command/TemplateHintsStatusCommand.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index d9af42ee33cb4..abe8e70677c60 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -11,6 +11,9 @@ use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +/** + * Command to show frontend template hints status + */ class TemplateHintsStatusCommand extends Command { @@ -57,8 +60,13 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $templateHintsStatus = ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; + $templateHintsStatus = + ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) + ? 'enabled' + : 'disabled'; $templateHintsMessage = __(self::SUCCESS_MESSAGE, ['status' => $templateHintsStatus]); $output->writeln("<info>" . $templateHintsMessage . "</info>"); + + return; } } From a8041a1fda3a598e3502c5fdb1b7bd9a157befd1 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Tue, 21 Jan 2020 09:47:57 +0100 Subject: [PATCH 210/666] Add frontend template hints status command after suggestions --- .../Developer/Console/Command/TemplateHintsStatusCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index abe8e70677c60..b229c9a2b19fc 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -67,6 +67,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $templateHintsMessage = __(self::SUCCESS_MESSAGE, ['status' => $templateHintsStatus]); $output->writeln("<info>" . $templateHintsMessage . "</info>"); - return; + return 0; } } From 80b8514a601923b66abb8492e0868ad7fb5dfb1f Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Tue, 21 Jan 2020 14:59:12 +0200 Subject: [PATCH 211/666] cover gallery.js with jasmine test --- .../tests/lib/mage/gallery/gallery.test.js | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js new file mode 100644 index 0000000000000..d40681fd944c3 --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js @@ -0,0 +1,100 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'mage/gallery/gallery', + 'jquery' +], function (Gallery, $) { + 'use strict'; + + var gallery, + options, + element; + + beforeEach(function () { + options = { + options: { + allowfullscreen: true, + arrows: true, + height: 700, + keyboard: true, + loop: true, + nav: 'thumbs', + navarrows: true, + navdir: 'horizontal', + navtype: 'slides', + showCaption: false, + thumbheight: 110, + thumbwidth: 88, + transition: 'slide', + transitionduration: 500, + width: 700 + }, + fullscreen: { + arrows: true, + loop: true, + nav: 'thumbs', + navarrows: false, + navdir: 'horizontal', + navtype: 'slides', + showCaption: false, + transition: 'slide', + transitionduration: 500 + }, + breakpoints: { + mobile: {} + }, + data: [ + { + caption: 'Simple product', + isMain: true, + position: '1', + type: 'image', + videoUrl: null, + thumb: '', + full: '', + img: '' + } + ], + magnifierOpts: { + enabled: false, + eventType: 'hover', + fullscreenzoom: '20', + height: 100, + largeWrapper: '[data-gallery-role=\'magnifier\']', + left: 10, + mode: 'outside', + thumb: '.fotorama__img', + top: 10, + width: 100, + zoomable: false + } + }; + element = $('<div class="gallery-placeholder' + + ' _block-content-loading" data-gallery-role="gallery-placeholder">' + + '<img alt="main product photo" class="gallery-placeholder__image" src="">' + + '</div>'); + + spyOn($.fn, 'data').and.callFake(function () { + return { + setOptions: jasmine.createSpy().and.returnValue(true), + updateOptions: jasmine.createSpy().and.returnValue(true) + }; + }); + expect(); + gallery = new Gallery(options, element); + + }); + + describe('"initGallery" method', function () { + it('Verify gallery initialization', function () { + expect(gallery.settings.$elementF.class).toBe(element[1]); + expect(gallery.settings.fullscreenConfig).toBeDefined(); + expect(gallery.settings.fotoramaApi).toBeDefined(); + expect(gallery.settings.data).toBeDefined(); + expect(gallery.settings.api).toBeDefined(); + }); + }); +}); From 7a70a47677f64b7a4edf45c9e072a20b3deabeb8 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Tue, 21 Jan 2020 18:36:50 +0200 Subject: [PATCH 212/666] Unit Test for Magento\Fedex\Plugin\Block\DataProviders\Tracking\ChangeTitle --- .../Tracking/ChangeTitleTest.php | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php new file mode 100644 index 0000000000000..dc3218411b748 --- /dev/null +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Fedex\Test\Unit\Plugin\Block\DataProviders\Tracking; + +use Magento\Fedex\Plugin\Block\DataProviders\Tracking\ChangeTitle; +use Magento\Framework\Phrase; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Shipping\Block\DataProviders\Tracking\DeliveryDateTitle; +use Magento\Shipping\Model\Tracking\Result\Status; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for @see \Magento\Fedex\Plugin\Block\DataProviders\Tracking\ChangeTitle + */ +class ChangeTitleTest extends TestCase +{ + /** + * @var ChangeTitle|MockObject + */ + private $plugin; + + /** + * @inheritDoc + */ + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject(ChangeTitle::class); + } + + /** + * Check if Title was changed + * + * @param string $carrierCode + * @param string $originalResult + * @param Phrase|string $finalResult + * @dataProvider testAfterGetTitleDataProvider + */ + public function testAfterGetTitle($carrierCode, $originalResult, $finalResult) + { + /** @var DeliveryDateTitle|MockObject $subjectMock */ + $subjectMock = $this->getMockBuilder(DeliveryDateTitle::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var Status|MockObject $trackingStatusMock */ + $trackingStatusMock = $this->getMockBuilder(Status::class) + ->disableOriginalConstructor() + ->setMethods(['getCarrier']) + ->getMock(); + $trackingStatusMock->expects($this::once()) + ->method('getCarrier') + ->willReturn($carrierCode); + + $actual = $this->plugin->afterGetTitle($subjectMock, $originalResult, $trackingStatusMock); + + $this->assertEquals($finalResult, $actual); + } + + /** + * Data provider + * + * @return array + */ + public function testAfterGetTitleDataProvider() + { + return [ + [\Magento\Fedex\Model\Carrier::CODE, 'Original Title', __('Expected Delivery:')], + ['not-fedex', 'Original Title', 'Original Title'], + ]; + } +} From c4c5d736e179d8f6055255eb075b7c3cc705ce58 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Tue, 21 Jan 2020 18:33:03 +0100 Subject: [PATCH 213/666] Add frontend template hints status command after suggestions --- .../Console/Command/TemplateHintsStatusCommand.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index b229c9a2b19fc..296d5dd7ac82d 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -16,17 +16,9 @@ */ class TemplateHintsStatusCommand extends Command { - - /** - * command name - */ + const COMMAND_NAME = 'dev:template-hints:status'; - /** - * Success message - */ - const SUCCESS_MESSAGE = "Template hints are %status"; - /** * @var ScopeConfigInterface */ @@ -64,7 +56,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) ? 'enabled' : 'disabled'; - $templateHintsMessage = __(self::SUCCESS_MESSAGE, ['status' => $templateHintsStatus]); + $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); $output->writeln("<info>" . $templateHintsMessage . "</info>"); return 0; From ab1b1de0294314503af16d5b346e5e2536542210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Tue, 21 Jan 2020 19:06:21 +0100 Subject: [PATCH 214/666] magento/magento2#26479 Clear notice if Autoloader was not registered properly, instead of passing the error to higher levels --- .../Magento/Framework/Autoload/AutoloaderRegistry.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php b/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php index f051d215808a3..7a7e3501f89bd 100644 --- a/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php +++ b/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php @@ -34,12 +34,12 @@ public static function registerAutoloader(AutoloaderInterface $newAutoloader) * @throws \Exception * @return AutoloaderInterface */ - public static function getAutoloader() + public static function getAutoloader(): AutoloaderInterface { - if (self::$autoloader !== null) { - return self::$autoloader; - } else { + if (!self::$autoloader instanceof AutoloaderInterface) { throw new \Exception('Autoloader is not registered, cannot be retrieved.'); } + + return self::$autoloader; } } From bf775238f24f2a60e36a252e3cac937d743fb328 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Tue, 21 Jan 2020 20:58:10 +0200 Subject: [PATCH 215/666] Unit test for Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate --- .../Block/Tracking/PopupDeliveryDateTest.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php new file mode 100644 index 0000000000000..23465b1b26a42 --- /dev/null +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Fedex\Test\Unit\Plugin\Block\Tracking; + +use Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Shipping\Block\Tracking\Popup; +use Magento\Shipping\Model\Tracking\Result\Status; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for @see \Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate + */ +class PopupDeliveryDateTest extends TestCase +{ + /** + * @var MockObject|PopupDeliveryDate + */ + private $plugin; + + /** + * @inheritDoc + */ + protected function setUp() + { + $objectManagerHelper = new ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject(PopupDeliveryDate::class); + } + + /** + * Test the method with Fedex carrier + */ + public function testAfterFormatDeliveryDateTimeWithFedexCarrier() + { + /** @var Status|MockObject $trackingStatusMock */ + $trackingStatusMock = $this->getMockBuilder(Status::class) + ->disableOriginalConstructor() + ->setMethods(['getCarrier']) + ->getMock(); + $trackingStatusMock->expects($this::once()) + ->method('getCarrier') + ->willReturn(\Magento\Fedex\Model\Carrier::CODE); + + /** @var Popup|MockObject $subjectMock */ + $subjectMock = $this->getMockBuilder(Popup::class) + ->disableOriginalConstructor() + ->setMethods(['formatDeliveryDate', 'getTrackingInfo']) + ->getMock(); + $subjectMock->expects($this->once()) + ->method('getTrackingInfo') + ->willReturn([[$trackingStatusMock]]); + $subjectMock->expects($this->once()) + ->method('formatDeliveryDate'); + + $this->plugin->afterFormatDeliveryDateTime($subjectMock, 'Test Result', '2020-02-02', '12:00'); + } + + /** + * Test the method with a different carrier + */ + public function testAfterFormatDeliveryDateTimeWithOtherCarrier() + { + /** @var Status|MockObject $trackingStatusMock */ + $trackingStatusMock = $this->getMockBuilder(Status::class) + ->disableOriginalConstructor() + ->setMethods(['getCarrier']) + ->getMock(); + $trackingStatusMock->expects($this::once()) + ->method('getCarrier') + ->willReturn('not-fedex'); + + /** @var Popup|MockObject $subjectMock */ + $subjectMock = $this->getMockBuilder(Popup::class) + ->disableOriginalConstructor() + ->setMethods(['formatDeliveryDate', 'getTrackingInfo']) + ->getMock(); + $subjectMock->expects($this->once()) + ->method('getTrackingInfo') + ->willReturn([[$trackingStatusMock]]); + $subjectMock->expects($this->never()) + ->method('formatDeliveryDate'); + + $this->plugin->afterFormatDeliveryDateTime($subjectMock, 'Test Result', '2020-02-02', '12:00'); + } +} From af8e6663d97ded8ab24727282efa253340a32773 Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Tue, 21 Jan 2020 14:24:31 -0600 Subject: [PATCH 216/666] MC-24172: Fix Skipped MFTF Tests From MC-17140: MC-14770, MC-14771, MC-14772 - add sorting to fix product ordering --- .../ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index 514366fa45c52..02d6d90ae5d0e 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -114,6 +114,11 @@ <!-- Navigate to category on store front --> <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> + <!-- Sort products By Price --> + <actionGroup ref="StorefrontCategoryPageSortProductActionGroup" stepKey="sortProductByPrice"/> + <!-- Set Ascending Direction --> + <actionGroup ref="StorefrontCategoryPageSortAscendingActionGroup" stepKey="setAscendingDirection"/> + <!-- Check simple product name on store front category page --> <actionGroup ref="AssertProductDetailsOnStorefrontActionGroup" stepKey="storefrontProduct1Name"> <argument name="productInfo" value="$createSimpleProduct.name$"/> From 5a0bea09d0e2797f5f878bfe39bcce4dd31e0bc9 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 22 Jan 2020 10:47:19 +0200 Subject: [PATCH 217/666] MC-30391: Category not considered Configurable product in cart rule --- .../Model/Rule/Condition/Product/Combine.php | 3 +- .../Model/Rule/Condition/ProductTest.php | 32 +++++++-- .../_files/rules_parent_category.php | 66 +++++++++++++++++++ .../_files/rules_parent_category_rollback.php | 21 ++++++ 4 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category.php create mode 100644 dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category_rollback.php diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Combine.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Combine.php index 1649dea80ef5b..6ade7a064e849 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Combine.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product/Combine.php @@ -145,7 +145,8 @@ private function validateEntity($cond, \Magento\Framework\Model\AbstractModel $e private function retrieveValidateEntities($attributeScope, \Magento\Framework\Model\AbstractModel $entity) { if ($attributeScope === 'parent') { - $validateEntities = [$entity]; + $parentItem = $entity->getParentItem(); + $validateEntities = $parentItem ? [$parentItem] : [$entity]; } elseif ($attributeScope === 'children') { $validateEntities = $entity->getChildren() ?: [$entity]; } else { diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php index 70fa11fc78c87..abdb38897004d 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php @@ -11,6 +11,9 @@ use Magento\Quote\Api\Data\CartInterface; use Magento\SalesRule\Api\RuleRepositoryInterface; +use Magento\Framework\Registry; +use Magento\SalesRule\Model\Rule; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -50,8 +53,8 @@ public function testValidateCategorySalesRuleIncludesChildren($categoryId, $expe ->load('test_cart_with_configurable', 'reserved_order_id'); // Load the SalesRule looking for products in a specific category - /** @var $rule \Magento\SalesRule\Model\Rule */ - $rule = $this->objectManager->get(\Magento\Framework\Registry::class) + /** @var $rule Rule */ + $rule = $this->objectManager->get(Registry::class) ->registry('_fixture/Magento_SalesRule_Category'); // Prepare the parent product with the given category setting @@ -80,8 +83,8 @@ public function testValidateSalesRuleExcludesBundleChildren(): void ->load('test_cart_with_bundle_and_options', 'reserved_order_id'); // Load the SalesRule looking for excluding products with selected sku - /** @var $rule \Magento\SalesRule\Model\Rule */ - $rule = $this->objectManager->get(\Magento\Framework\Registry::class) + /** @var $rule Rule */ + $rule = $this->objectManager->get(Registry::class) ->registry('_fixture/Magento_SalesRule_Sku_Exclude'); $this->assertEquals(false, $rule->validate($quote)); @@ -172,4 +175,25 @@ private function getSalesRule(string $name): \Magento\SalesRule\Model\Rule return $converter->toModel($rule); } + + /** + * Ensure that SalesRules filtering on quote items quantity validates configurable product parent category correctly + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php + * @magentoDataFixture Magento/SalesRule/_files/rules_parent_category.php + */ + public function testValidateParentCategoryWithConfigurable() + { + $quote = $this->getQuote('test_cart_with_configurable'); + $registry = $this->objectManager->get(Registry::class); + /** @var Rule $rule */ + $rule = $this->objectManager->create(Rule::class); + $ruleId = $registry->registry('50% Off on Configurable parent category'); + $rule->load($ruleId); + + $this->assertFalse( + $rule->validate($quote->getBillingAddress()), + 'Cart price rule validation failed.' + ); + } } diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category.php new file mode 100644 index 0000000000000..c525fa7152447 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var Registry $registry */ +$registry = Bootstrap::getObjectManager()->get(Registry::class); +/** @var \Magento\SalesRule\Model\Rule $rule */ +$salesRule = Bootstrap::getObjectManager()->create(\Magento\SalesRule\Model\Rule::class); +$salesRule->setData( + [ + 'name' => '50% Off on Configurable parent category', + 'is_active' => 1, + 'customer_group_ids' => [\Magento\Customer\Model\GroupManagement::NOT_LOGGED_IN_ID], + 'coupon_type' => \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON, + 'simple_action' => 'by_percent', + 'discount_amount' => 50, + 'discount_step' => 0, + 'stop_rules_processing' => 1, + 'website_ids' => [ + Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class + )->getWebsite()->getId() + ] + ] +); + +$salesRule->getConditions()->loadArray([ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class, + 'attribute' => null, + 'operator' => null, + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Subselect::class, + 'attribute' => 'qty', + 'operator' => '==', + 'value' => '1', + 'is_value_processed' => null, + 'aggregator' => 'all', + 'conditions' => + [ + [ + 'type' => \Magento\SalesRule\Model\Rule\Condition\Product::class, + 'attribute' => 'category_ids', + 'attribute_scope' => 'parent', + 'operator' => '!=', + 'value' => '2', + 'is_value_processed' => false, + ], + ], + ], + ], +]); + +$salesRule->save(); +$registry->unregister('50% Off on Configurable parent category'); +$registry->register('50% Off on Configurable parent category', $salesRule->getRuleId()); diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category_rollback.php new file mode 100644 index 0000000000000..edefd5e1650e7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/rules_parent_category_rollback.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\SalesRule\Model\Rule; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Registry; + +/** @var Registry $registry */ +$registry = Bootstrap::getObjectManager()->get(Registry::class); +$rule = Bootstrap::getObjectManager()->get(Rule::class); + +/** @var Rule $rule */ +$ruleId = $registry->registry('50% Off on Configurable parent category'); +$rule->load($ruleId); +if ($rule->getId()) { + $rule->delete(); +} From 2312289f29c2dbc84e2ab23c745cfc3c9e30cd42 Mon Sep 17 00:00:00 2001 From: "Rav [RedChamps]" <rav@redchamps.com> Date: Wed, 22 Jan 2020 14:21:56 +0530 Subject: [PATCH 218/666] checked if quote object contains id before looking for quote items --- app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php index 3709f4914c477..ec4bd93ee4ff0 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Cart.php @@ -105,14 +105,13 @@ protected function _prepareCollection() { $quote = $this->getQuote(); - if ($quote) { + if ($quote && $quote->getId()) { $collection = $quote->getItemsCollection(false); + $collection->addFieldToFilter('parent_item_id', ['null' => true]); } else { $collection = $this->_dataCollectionFactory->create(); } - $collection->addFieldToFilter('parent_item_id', ['null' => true]); - $this->setCollection($collection); return parent::_prepareCollection(); From c5991d3c719d68f66c64f5f10978b6412021165c Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 22 Jan 2020 10:57:13 +0200 Subject: [PATCH 219/666] Refactoring test to remove object after test --- .../tests/lib/mage/gallery/gallery.test.js | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js index d40681fd944c3..c18728acaf948 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js @@ -11,7 +11,9 @@ define([ var gallery, options, - element; + element, + jqueryDataMock, + originSpy; beforeEach(function () { options = { @@ -76,25 +78,25 @@ define([ ' _block-content-loading" data-gallery-role="gallery-placeholder">' + '<img alt="main product photo" class="gallery-placeholder__image" src="">' + '</div>'); - - spyOn($.fn, 'data').and.callFake(function () { - return { - setOptions: jasmine.createSpy().and.returnValue(true), - updateOptions: jasmine.createSpy().and.returnValue(true) - }; - }); - expect(); - gallery = new Gallery(options, element); - }); describe('"initGallery" method', function () { it('Verify gallery initialization', function () { + originSpy = $.fn.data; + jqueryDataMock = { + setOptions: jasmine.createSpy().and.returnValue(true), + updateOptions: jasmine.createSpy().and.returnValue(true) + } + spyOn($.fn, 'data').and.callFake(function () { return jqueryDataMock }); + + gallery = new Gallery(options, element); expect(gallery.settings.$elementF.class).toBe(element[1]); expect(gallery.settings.fullscreenConfig).toBeDefined(); expect(gallery.settings.fotoramaApi).toBeDefined(); expect(gallery.settings.data).toBeDefined(); expect(gallery.settings.api).toBeDefined(); + + $.fn.data = originSpy; }); }); }); From 41f07fcc674ef4aee5e5234cc71e6a3ac71aba45 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 22 Jan 2020 11:11:51 +0200 Subject: [PATCH 220/666] static test fix --- .../Search/Model/PopularSearchTerms.php | 2 +- .../Model/ResourceModel/Query/Collection.php | 52 ++++++++++++------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Search/Model/PopularSearchTerms.php b/app/code/Magento/Search/Model/PopularSearchTerms.php index 213fac0232535..0a3a7de4e1271 100644 --- a/app/code/Magento/Search/Model/PopularSearchTerms.php +++ b/app/code/Magento/Search/Model/PopularSearchTerms.php @@ -7,7 +7,7 @@ namespace Magento\Search\Model; /** - * Popular search terms + * Finds top search results in search */ class PopularSearchTerms { diff --git a/app/code/Magento/Search/Model/ResourceModel/Query/Collection.php b/app/code/Magento/Search/Model/ResourceModel/Query/Collection.php index c9a983dd8589b..2fc71fc6a6d73 100644 --- a/app/code/Magento/Search/Model/ResourceModel/Query/Collection.php +++ b/app/code/Magento/Search/Model/ResourceModel/Query/Collection.php @@ -5,15 +5,25 @@ */ namespace Magento\Search\Model\ResourceModel\Query; +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; +use Magento\Framework\Data\Collection\EntityFactoryInterface; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Helper; +use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Psr\Log\LoggerInterface; /** * Search query collection * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection +class Collection extends AbstractCollection { /** * Store for filter @@ -25,36 +35,38 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab /** * Store manager * - * @var \Magento\Store\Model\StoreManagerInterface + * @var StoreManagerInterface */ protected $_storeManager; /** * Search resource helper * - * @var \Magento\Framework\DB\Helper + * @var Helper */ protected $_resourceHelper; /** - * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\DB\Helper $resourceHelper - * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection - * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource + * Constructor + * + * @param EntityFactoryInterface $entityFactory + * @param LoggerInterface $logger + * @param FetchStrategyInterface $fetchStrategy + * @param ManagerInterface $eventManager + * @param StoreManagerInterface $storeManager + * @param Helper $resourceHelper + * @param AdapterInterface $connection + * @param AbstractDb $resource */ public function __construct( - \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\DB\Helper $resourceHelper, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null + EntityFactoryInterface $entityFactory, + LoggerInterface $logger, + FetchStrategyInterface $fetchStrategy, + ManagerInterface $eventManager, + StoreManagerInterface $storeManager, + Helper $resourceHelper, + AdapterInterface $connection = null, + AbstractDb $resource = null ) { $this->_storeManager = $storeManager; $this->_resourceHelper = $resourceHelper; @@ -178,7 +190,7 @@ public function isTopSearchResult(string $term, int $storeId, int $maxCountCache return $this->getSize() > 0; } - + /** * Set Recent Queries Order * From 030172abae997b093b74eb76179da676b5762af0 Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Wed, 22 Jan 2020 11:53:53 +0200 Subject: [PATCH 221/666] MC-24168: Fix Skipped MFTF Tests From MC-17140: MAGETWO-95175, MAGETWO-97001, MAGETWO-98189 --- .../Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml index 39e6e316dd486..dfed39e861f05 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCheckCreditMemoTotalsTest.xml @@ -15,7 +15,7 @@ <title value="Checking Credit memo Totals"/> <description value="Checking Credit memo Totals"/> <severity value="MAJOR"/> - <testCaseId value="MC-6159"/> + <testCaseId value="MC-25752"/> <group value="tax"/> <group value="sales"/> </annotations> @@ -23,7 +23,6 @@ <!-- Create productTaxClass --> <createData entity="productTaxClass" stepKey="createProductTaxClass"/> <!--Set configs--> - <magentoCLI command="config:set {{DisableGenerateCategoryProductUrlRewritesConfigData.path}} {{DisableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="disableGenerateUrlRewrite"/> <magentoCLI command="config:set {{DefaultProductTaxClass.path}} $createProductTaxClass.return$" stepKey="setDefaultProductTaxClass"/> <!--Create category and product--> <createData entity="_defaultCategory" stepKey="createCategory"/> @@ -42,7 +41,6 @@ </before> <after> <!--Set configs--> - <magentoCLI command="config:set {{EnableGenerateCategoryProductUrlRewritesConfigData.path}} {{EnableGenerateCategoryProductUrlRewritesConfigData.value}}" stepKey="enableGenerateUrlRewrite"/> <magentoCLI command="config:set {{DefaultProductTaxClass.path}} {{DefaultProductTaxClass.value}}" stepKey="setDefaultProductTaxClass"/> <!--Delete category and product--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> From acdc9b429bfab2a9aa496f571d9ccc37d0b6492d Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 22 Jan 2020 11:54:55 +0200 Subject: [PATCH 222/666] fix static tests --- .../jasmine/tests/lib/mage/gallery/gallery.test.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js index c18728acaf948..7700c3d64a1b7 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery/gallery.test.js @@ -3,6 +3,7 @@ * See COPYING.txt for license details. */ +/* eslint-disable max-nested-callbacks */ define([ 'mage/gallery/gallery', 'jquery' @@ -83,12 +84,14 @@ define([ describe('"initGallery" method', function () { it('Verify gallery initialization', function () { originSpy = $.fn.data; - jqueryDataMock = { + jqueryDataMock = { setOptions: jasmine.createSpy().and.returnValue(true), updateOptions: jasmine.createSpy().and.returnValue(true) - } - spyOn($.fn, 'data').and.callFake(function () { return jqueryDataMock }); - + }; + spyOn($.fn, 'data').and.callFake(function () { + return jqueryDataMock; + }); + gallery = new Gallery(options, element); expect(gallery.settings.$elementF.class).toBe(element[1]); expect(gallery.settings.fullscreenConfig).toBeDefined(); @@ -96,7 +99,7 @@ define([ expect(gallery.settings.data).toBeDefined(); expect(gallery.settings.api).toBeDefined(); - $.fn.data = originSpy; + $.fn.data = originSpy; }); }); }); From a55547993a584ee9452fb0c7331364f495b2a067 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Wed, 22 Jan 2020 12:04:44 +0200 Subject: [PATCH 223/666] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- ...lsAreNotVisibleWithoutHoverActionGroup.xml | 19 ++++ ...ctControlsAreVisibleOnHoverActionGroup.xml | 19 ++++ ...refrontNavigateCategoryPageActionGroup.xml | 1 + .../Section/StorefrontCategoryMainSection.xml | 4 + ...ogProductsListWidgetOptionsActionGroup.xml | 33 +++++++ .../Mftf/Section/CatalogWidgetSection.xml | 1 + ...frontProductGridUIUpdatesOnDesktopTest.xml | 95 +++++++++++++++++++ .../AdminClickInsertWidgetActionGroup.xml | 19 ++++ ...nsertWidgetToCmsPageContentActionGroup.xml | 25 +++++ ...ddToWishListIconIsClickableActionGroup.xml | 23 +++++ 10 files changed, 239 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml create mode 100644 app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml create mode 100644 app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminInsertWidgetToCmsPageContentActionGroup.xml create mode 100644 app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml 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..8d18c49d6a624 --- /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.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> + <dontSeeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" 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..9c26dcecf726a --- /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.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> + </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/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 9a84f90edcfc0..8f2ba2016aea6 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"/> + <element name="toWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> + <element name="toCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> <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="//div[@class='product-item-info']//a[contains(text(), '{{productName}}')]//..//..//span[@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/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml new file mode 100644 index 0000000000000..a5b3078dbdcc4 --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.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/StorefrontProductGridUIUpdatesOnDesktopTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml new file mode 100644 index 0000000000000..fde10352ab2ba --- /dev/null +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml @@ -0,0 +1,95 @@ +<?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"/> + <!-- TODO: REMOVE AFTER FIX MC-29943 --> + <magentoCLI command="indexer:reindex" stepKey="performReindex"/> + </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="logout" 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/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml new file mode 100644 index 0000000000000..2ec329bf174b3 --- /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.</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/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/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml new file mode 100644 index 0000000000000..77984a048c5ff --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.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="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup"> + <annotations> + <description>Assert AddToWishList icon is clickable</description> + </annotations> + + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> + <click selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> + <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> + <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> From 0263b4cad75f368c010b5077df6bc9c22dc1ce5b Mon Sep 17 00:00:00 2001 From: Andrew Chorniy <a.chorniy@atwix.com> Date: Wed, 22 Jan 2020 12:27:08 +0200 Subject: [PATCH 224/666] Fixed type issue. Create unit test for customer data model --- .../Magento/Customer/Model/Data/Customer.php | 4 +- .../Test/Unit/Model/Data/CustomerTest.php | 74 +++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php diff --git a/app/code/Magento/Customer/Model/Data/Customer.php b/app/code/Magento/Customer/Model/Data/Customer.php index 7a135904f6663..27a82d7f8d8f3 100644 --- a/app/code/Magento/Customer/Model/Data/Customer.php +++ b/app/code/Magento/Customer/Model/Data/Customer.php @@ -94,7 +94,7 @@ public function getCreatedAt() */ public function getCreatedIn() { - return $this->_get(self::CREATED_IN); + return (string)$this->_get(self::CREATED_IN); } /** @@ -150,7 +150,7 @@ public function getGender() /** * Get group id * - * @return string|null + * @return int|null */ public function getGroupId() { diff --git a/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php new file mode 100644 index 0000000000000..945f213d015bd --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php @@ -0,0 +1,74 @@ +<?php + +namespace Magento\Customer\Test\Unit\Model\Data; + +use Magento\Customer\Model\Data\Customer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for customer data model + */ +class CustomerTest extends TestCase +{ + /** @var Customer */ + protected $model; + + /** @var ObjectManager */ + protected $objectManager; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + + $this->model = $this->objectManager->getObject(Customer::class); + } + + /** + * Test getGroupId() + * + * @return void + */ + public function testGetGroupId() + { + $testGroupId = 3; + $this->model->setGroupId($testGroupId); + $this->assertEquals($testGroupId, $this->model->getGroupId()); + } + + /** + * Test getCreatedIn() + * + * @param array|string $options + * @param array $expectedResult + * + * @dataProvider getCreatedInDataProvider + * + * @return void + */ + public function testGetCreatedIn($options, $expectedResult) + { + for ($i = 0; $i < count($options); $i++) { + $this->model->setCreatedIn($options[$i]); + for ($j = $i; $j < count($expectedResult); $j++) { + $this->assertEquals($expectedResult[$j], $this->model->getCreatedIn()); + break; + } + } + } + + /** + * Data provider for testGetCreatedIn + * + * @return array + */ + public function getCreatedInDataProvider() + { + return [ + 'array' => [ + 'options' => ['Default', 'Admin', 'US'], + 'expectedResult' => ['Default', 'Admin', 'US'] + ] + ]; + } +} From c42ebc1c298c6262bbdf35e0a8682b693b8186d9 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Wed, 22 Jan 2020 13:47:35 +0200 Subject: [PATCH 225/666] #8691: improved cases for DictionaryTest --- .../Framework/App/Language/DictionaryTest.php | 50 ++++++++++++++++++- .../_files/bar/{en_us => en_az}/a.csv | 0 .../_files/bar/{en_us => en_az}/b.csv | 0 .../_files/bar/{en_us => en_az}/language.xml | 4 +- .../bar/{en_us => en_az}/registration.php | 2 +- .../Language/_files/bar/en_gb/language.xml | 2 +- .../App/Language/_files/baz/en_gb/1.csv | 6 ++- .../App/Language/_files/devdoc/en_ak/1.csv | 3 ++ .../Language/_files/devdoc/en_ak/language.xml | 15 ++++++ .../_files/devdoc/en_ak/registration.php | 9 ++++ .../_files/first/{en_us => en_az}/1.csv | 0 .../first/{en_us => en_az}/language.xml | 4 +- .../first/{en_us => en_az}/registration.php | 2 +- .../parent-package-one/en_au_package/1.csv | 5 ++ .../en_au_package/language.xml | 14 ++++++ .../en_au_package/registration.php | 9 ++++ .../parent-package-one/en_ie_package/1.csv | 6 +++ .../en_ie_package/language.xml | 13 +++++ .../en_ie_package/registration.php | 9 ++++ .../language_package_one/1.csv | 4 ++ .../language_package_one/language.xml | 14 ++++++ .../language_package_one/registration.php | 9 ++++ .../parent-package-two/en_ca_package/1.csv | 8 +++ .../en_ca_package/language.xml | 14 ++++++ .../en_ca_package/registration.php | 9 ++++ .../parent-package-two/en_us_package/1.csv | 9 ++++ .../en_us_package/language.xml | 13 +++++ .../en_us_package/registration.php | 9 ++++ .../language_package_two/1.csv | 7 +++ .../language_package_two/language.xml | 14 ++++++ .../language_package_two/registration.php | 9 ++++ .../Language/_files/second/en_gb/language.xml | 2 +- .../Framework/App/Language/Dictionary.php | 4 ++ 33 files changed, 267 insertions(+), 11 deletions(-) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/{en_us => en_az}/a.csv (100%) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/{en_us => en_az}/b.csv (100%) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/{en_us => en_az}/language.xml (86%) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/{en_us => en_az}/registration.php (92%) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/{en_us => en_az}/1.csv (100%) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/{en_us => en_az}/language.xml (88%) rename dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/{en_us => en_az}/registration.php (91%) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/1.csv create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/language.xml create mode 100644 dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php index 363f84627350f..bc299053bd4fe 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php @@ -63,7 +63,9 @@ public function dictionaryDataProvider() // Second case with inheritance of package with the same language code 'a case with inheritance similar language code' => $this->getDataInheritanceWitSimilarCode(), // Third case with circular inheritance, when two packages depend on each other - 'a case with circular inheritance' => $this->getDataCircularInheritance() + 'a case with circular inheritance' => $this->getDataCircularInheritance(), + // Fourth case with multiple inheritance from dev docs + 'a case with multiple inheritance from dev docs' => $this->getDataMultipleInheritanceFromDevDocs() ]; } @@ -113,7 +115,7 @@ private function getDataCircularInheritance() { return [ // Dictionary that will be requested - 'language_code' => 'en_US', + 'language_code' => 'en_AZ', // Expected merged dictionary data 'expectation' => [ 'one' => '1.0', @@ -123,4 +125,48 @@ private function getDataCircularInheritance() ] ]; } + + /** + * If a language package inherits from two packages: + * ... + * <code>en_AK</code> + * ... + * <use vendor="parent-package-one" package="language_package_one"/> + * <use vendor= "parent-package-two" package="language_package_two"/> + * ... + * + * In the preceding example: + * language_package_one inherits from en_au_package and en_au_package inherits from en_ie_package + * language_package_two inherits from en_ca_package and en_ca_package inherits from en_us_package + * + * If the Magento application cannot find word or phrase in the en_AK package, + * it looks in other packages in following sequence: + * parent-package-one/language_package_one + * <vendorname>/en_au_package + * <vendorname>/en_ie_package + * parent-package-two/language_package_two + * <vendorname>/en_ca_package + * <vendorname>/en_us_package + * + * @return array + */ + private function getDataMultipleInheritanceFromDevDocs() + { + return [ + // Dictionary that will be requested + 'language_code' => 'en_AK', + // Expected merged dictionary data + 'expectation' => [ + 'one' => 'en_us_package_one', + 'two' => 'en_ca_package_two', + 'three' => 'language_package_two_three', + 'four' => 'en_ie_package_four', + 'five' => 'en_au_package_five', + 'six' => 'language_package_one_six', + 'seven' => 'en_ak_seven', + 'eight' => 'en_ak_eight', + 'nine' => 'en_ak_nine', + ] + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/a.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/a.csv similarity index 100% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/a.csv rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/a.csv diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/b.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/b.csv similarity index 100% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/b.csv rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/b.csv diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml similarity index 86% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml index a4c5630d5fcd9..3cc5d8965c2e8 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml @@ -6,8 +6,8 @@ */ --> <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> - <code>en_US</code> + <code>en_AZ</code> <vendor>bar</vendor> - <package>en_us</package> + <package>en_az</package> <sort_order>0</sort_order> </language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php similarity index 92% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php index 7f792bf5941ca..41e17fbcf515d 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php @@ -6,4 +6,4 @@ use Magento\Framework\Component\ComponentRegistrar; -ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'bar_en_us', __DIR__); +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'bar_en_az', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml index faf531fbf5cc2..736e9dbe738d7 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml @@ -10,5 +10,5 @@ <vendor>bar</vendor> <package>en_gb</package> <sort_order>100</sort_order> - <use package="en_us" vendor="bar"/> + <use package="en_az" vendor="bar"/> </language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv index ea501f9d96944..61ef9dd8a49b3 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv @@ -1 +1,5 @@ -four and 5/10,4.5 \ No newline at end of file +one,1.00 +two,2.00 +three,3.00 +four,4.00 +four and 5/10,4.5 diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv new file mode 100644 index 0000000000000..8ed274ad7d886 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv @@ -0,0 +1,3 @@ +seven,en_ak_seven +eight,en_ak_eight +nine,en_ak_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml new file mode 100644 index 0000000000000..d0db854f329d0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_AK</code> + <vendor>devdoc</vendor> + <package>en_ak</package> + <sort_order>0</sort_order> + <use vendor="parent-package-one" package="language_package_one"/> + <use vendor="parent-package-two" package="language_package_two"/> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php new file mode 100644 index 0000000000000..13b498edcd0aa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'devdoc_en_ak', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/1.csv similarity index 100% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/1.csv rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/1.csv diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/language.xml similarity index 88% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/language.xml rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/language.xml index 6c67871476b5f..2b8354a70dc28 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/language.xml @@ -6,9 +6,9 @@ */ --> <language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> - <code>en_US</code> + <code>en_AZ</code> <vendor>first</vendor> - <package>en_us</package> + <package>en_az</package> <sort_order>0</sort_order> <use package="en_gb" vendor="second"/> </language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php similarity index 91% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php index 48dfbf20c9f26..85e88eb4546ce 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php @@ -6,4 +6,4 @@ use Magento\Framework\Component\ComponentRegistrar; -ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'first_en_us', __DIR__); +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'first_en_az', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv new file mode 100644 index 0000000000000..f1d7dc7c106c7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv @@ -0,0 +1,5 @@ +five,en_au_package_five +six,en_au_package_six +seven,en_au_package_seven +eight,en_au_package_eight +nine,en_au_package_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml new file mode 100644 index 0000000000000..64d558d9c1d63 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-one</vendor> + <package>en_au_package</package> + <sort_order>0</sort_order> + <use vendor="parent-package-one" package="en_ie_package"/> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php new file mode 100644 index 0000000000000..664a6d34a814b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-one_en_au_package', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/1.csv new file mode 100644 index 0000000000000..8c580556c2e26 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/1.csv @@ -0,0 +1,6 @@ +four,en_ie_package_four +five,en_ie_package_five +six,en_ie_package_six +seven,en_ie_package_seven +eight,en_ie_package_eight +nine,en_ie_package_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/language.xml new file mode 100644 index 0000000000000..3b681d012b192 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/language.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-one</vendor> + <package>en_ie_package</package> + <sort_order>0</sort_order> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php new file mode 100644 index 0000000000000..81ae45c3d5a40 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-one_en_ie_package', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/1.csv new file mode 100644 index 0000000000000..54bb6bee04f17 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/1.csv @@ -0,0 +1,4 @@ +six,language_package_one_six +seven,language_package_one_seven +eight,language_package_one_eight +nine,language_package_one_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/language.xml new file mode 100644 index 0000000000000..4d19c728222ba --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/language.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-one</vendor> + <package>language_package_one</package> + <sort_order>0</sort_order> + <use vendor="parent-package-one" package="en_au_package"/> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php new file mode 100644 index 0000000000000..0432f835f0849 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-one_language_package_one', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/1.csv new file mode 100644 index 0000000000000..b3c5408b439b4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/1.csv @@ -0,0 +1,8 @@ +two,en_ca_package_two +three,en_ca_package_three +four,en_ca_package_four +five,en_ca_package_five +six,en_ca_package_six +seven,en_ca_package_seven +eight,en_ca_package_eight +nine,en_ca_package_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/language.xml new file mode 100644 index 0000000000000..68914dc8df672 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/language.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-two</vendor> + <package>en_ca_package</package> + <sort_order>0</sort_order> + <use vendor="parent-package-two" package="en_us_package"/> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php new file mode 100644 index 0000000000000..b87032884f7db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-two_en_ca_package', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/1.csv new file mode 100644 index 0000000000000..ef932c4326fb3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/1.csv @@ -0,0 +1,9 @@ +one,en_us_package_one +two,en_us_package_two +three,en_us_package_three +four,en_us_package_four +five,en_us_package_five +six,en_us_package_six +seven,en_us_package_seven +eight,en_us_package_eight +nine,en_us_package_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/language.xml new file mode 100644 index 0000000000000..fa7ecda34c975 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/language.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-two</vendor> + <package>en_us_package</package> + <sort_order>0</sort_order> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php new file mode 100644 index 0000000000000..48ed54033a96e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-two_en_us_package', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/1.csv new file mode 100644 index 0000000000000..ef85e7dd72575 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/1.csv @@ -0,0 +1,7 @@ +three,language_package_two_three +four,language_package_two_four +five,language_package_two_five +six,language_package_two_six +seven,language_package_two_seven +eight,language_package_two_eight +nine,language_package_two_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/language.xml new file mode 100644 index 0000000000000..5e72723312c68 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/language.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** +* Copyright © Magento, Inc. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<language xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/Language/package.xsd"> + <code>en_US</code> + <vendor>parent-package-two</vendor> + <package>language_package_two</package> + <sort_order>0</sort_order> + <use vendor="parent-package-two" package="en_ca_package"/> +</language> diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php new file mode 100644 index 0000000000000..f7eb7d2373a29 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'parent-package-two_language_package_two', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/second/en_gb/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/second/en_gb/language.xml index 860e21ad009ab..12f36154efffe 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/second/en_gb/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/second/en_gb/language.xml @@ -10,5 +10,5 @@ <vendor>second</vendor> <package>en_gb</package> <sort_order>0</sort_order> - <use package="en_us" vendor="first"/> + <use package="en_az" vendor="first"/> </language> diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php index 9aaafc23c9e49..b4a6fdc1b5ce3 100644 --- a/lib/internal/Magento/Framework/App/Language/Dictionary.php +++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php @@ -195,6 +195,10 @@ private function collectInheritedPacks($languageConfig, &$result, $level = 0, ar */ private function addInheritedPacks($packs, $pack, &$sortedPacks) { + if (isset($sortedPacks[$pack['key']])) { + return; + } + $sortedPacks[$pack['key']] = $pack; foreach ($pack['language']->getUses() as $reuse) { $packKey = implode('|', [$reuse['vendor'], $reuse['package']]); From 7bfc9902c6b01e337fcbdae402d8525271a63b65 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 21 Jan 2020 16:36:03 +0200 Subject: [PATCH 226/666] magento/magento2#: Remove a redundant call to DB for guest session --- app/code/Magento/Customer/Model/Session.php | 12 +- .../Customer/Test/Unit/Model/SessionTest.php | 132 ++++++++++++++---- 2 files changed, 116 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/Customer/Model/Session.php b/app/code/Magento/Customer/Model/Session.php index e9dc7700ec090..7fb02a14bc09b 100644 --- a/app/code/Magento/Customer/Model/Session.php +++ b/app/code/Magento/Customer/Model/Session.php @@ -19,6 +19,7 @@ * @method string getNoReferer() * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) + * @SuppressWarnings(PHPMD.TooManyFields) * @since 100.0.2 */ class Session extends \Magento\Framework\Session\SessionManager @@ -98,6 +99,11 @@ class Session extends \Magento\Framework\Session\SessionManager */ protected $_httpContext; + /** + * @var AccountConfirmation + */ + protected $accountConfirmation; + /** * @var GroupManagementInterface */ @@ -304,7 +310,11 @@ public function setCustomer(Customer $customerModel) public function getCustomer() { if ($this->_customerModel === null) { - $this->_customerModel = $this->_customerFactory->create()->load($this->getCustomerId()); + $this->_customerModel = $this->_customerFactory->create(); + + if ($this->getCustomerId()) { + $this->_customerResource->load($this->_customerModel, $this->getCustomerId()); + } } return $this->_customerModel; diff --git a/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php b/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php index 8565790990df1..00f376c4b81bc 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php @@ -7,48 +7,67 @@ */ namespace Magento\Customer\Test\Unit\Model; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\CustomerInterface; +use Magento\Customer\Model\Customer; +use Magento\Customer\Model\CustomerFactory; +use Magento\Customer\Model\ResourceModel\Customer as ResourceCustomer; +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Session\Storage; +use Magento\Framework\App\Http\Context; +use Magento\Framework\App\Response\Http; +use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\UrlFactory; +use PHPUnit\Framework\MockObject\MockObject; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SessionTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ResourceCustomer|MockObject + */ + protected $_customerResourceMock; + + /** + * @var Storage|MockObject */ protected $_storageMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ManagerInterface|MockObject */ protected $_eventManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Context|MockObject */ protected $_httpContextMock; /** - * @var \Magento\Framework\UrlFactory|\PHPUnit_Framework_MockObject_MockObject + * @var UrlFactory|MockObject */ protected $urlFactoryMock; /** - * @var \Magento\Customer\Model\CustomerFactory|\PHPUnit_Framework_MockObject_MockObject + * @var CustomerFactory|MockObject */ protected $customerFactoryMock; /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CustomerRepositoryInterface|MockObject */ protected $customerRepositoryMock; /** - * @var \Magento\Framework\App\Response\Http|\PHPUnit_Framework_MockObject_MockObject + * @var Http|MockObject */ protected $responseMock; /** - * @var \Magento\Customer\Model\Session + * @var Session */ protected $_model; @@ -58,21 +77,25 @@ class SessionTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->_storageMock = $this->createPartialMock( - \Magento\Customer\Model\Session\Storage::class, + Storage::class, ['getIsCustomerEmulated', 'getData', 'unsIsCustomerEmulated', '__sleep', '__wakeup'] ); - $this->_eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $this->_httpContextMock = $this->createMock(\Magento\Framework\App\Http\Context::class); - $this->urlFactoryMock = $this->createMock(\Magento\Framework\UrlFactory::class); - $this->customerFactoryMock = $this->getMockBuilder(\Magento\Customer\Model\CustomerFactory::class) + $this->_eventManagerMock = $this->createMock(ManagerInterface::class); + $this->_httpContextMock = $this->createMock(Context::class); + $this->urlFactoryMock = $this->createMock(UrlFactory::class); + $this->customerFactoryMock = $this->getMockBuilder(CustomerFactory::class) ->disableOriginalConstructor() - ->setMethods(['create', 'save']) + ->setMethods(['create']) ->getMock(); - $this->customerRepositoryMock = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class); + $this->_customerResourceMock = $this->getMockBuilder(ResourceCustomer::class) + ->disableOriginalConstructor() + ->setMethods(['load']) + ->getMock(); + $this->customerRepositoryMock = $this->createMock(CustomerRepositoryInterface::class); + $helper = new ObjectManagerHelper($this); + $this->responseMock = $this->createMock(Http::class); $this->_model = $helper->getObject( - \Magento\Customer\Model\Session::class, + Session::class, [ 'customerFactory' => $this->customerFactoryMock, 'storage' => $this->_storageMock, @@ -81,6 +104,7 @@ protected function setUp() 'urlFactory' => $this->urlFactoryMock, 'customerRepository' => $this->customerRepositoryMock, 'response' => $this->responseMock, + '_customerResource' => $this->_customerResourceMock, ] ); } @@ -90,8 +114,8 @@ protected function setUp() */ public function testSetCustomerAsLoggedIn() { - $customer = $this->createMock(\Magento\Customer\Model\Customer::class); - $customerDto = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + $customer = $this->createMock(Customer::class); + $customerDto = $this->createMock(CustomerInterface::class); $customer->expects($this->any()) ->method('getDataModel') ->will($this->returnValue($customerDto)); @@ -113,8 +137,8 @@ public function testSetCustomerAsLoggedIn() */ public function testSetCustomerDataAsLoggedIn() { - $customer = $this->createMock(\Magento\Customer\Model\Customer::class); - $customerDto = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + $customer = $this->createMock(Customer::class); + $customerDto = $this->createMock(CustomerInterface::class); $this->customerFactoryMock->expects($this->once()) ->method('create') @@ -185,19 +209,22 @@ public function testLoginById() */ protected function prepareLoginDataMock($customerId) { - $customerDataMock = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + $customerDataMock = $this->createMock(CustomerInterface::class); $customerDataMock->expects($this->once()) ->method('getId') ->will($this->returnValue($customerId)); $customerMock = $this->createPartialMock( - \Magento\Customer\Model\Customer::class, - ['getId', 'getConfirmation', 'updateData', 'getGroupId'] + Customer::class, + ['getId', 'isConfirmationRequired', 'getConfirmation', 'updateData', 'getGroupId'] ); - $customerMock->expects($this->exactly(3)) + $customerMock->expects($this->once()) ->method('getId') ->will($this->returnValue($customerId)); $customerMock->expects($this->once()) + ->method('isConfirmationRequired') + ->will($this->returnValue(true)); + $customerMock->expects($this->never()) ->method('getConfirmation') ->will($this->returnValue($customerId)); @@ -259,8 +286,59 @@ public function getIsLoggedInDataProvider() */ public function testSetCustomerRemovesFlagThatShowsIfCustomerIsEmulated() { - $customerMock = $this->createMock(\Magento\Customer\Model\Customer::class); + $customerMock = $this->createMock(Customer::class); $this->_storageMock->expects($this->once())->method('unsIsCustomerEmulated'); $this->_model->setCustomer($customerMock); } + /** + * Test "getCustomer()" for guest user + * + * @return void + */ + public function testGetCustomerForGuestUser() + { + $customerMock = $this->getMockBuilder(Customer::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->customerFactoryMock + ->expects($this->once()) + ->method('create') + ->will($this->returnValue($customerMock)); + + $this->assertSame($customerMock, $this->_model->getCustomer()); + } + + /** + * Test "getCustomer()" for registered user + * + * @return void + */ + public function testGetCustomerForRegisteredUser() + { + $customerId = 1; + + $customerMock = $this->getMockBuilder(Customer::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->customerFactoryMock + ->expects($this->once()) + ->method('create') + ->will($this->returnValue($customerMock)); + + $this->_storageMock + ->expects($this->exactly(4)) + ->method('getData') + ->with('customer_id') + ->willReturn($customerId); + + $this->_customerResourceMock + ->expects($this->once()) + ->method('load') + ->with($customerMock, $customerId) + ->will($this->returnValue($customerMock)); + + $this->assertSame($customerMock, $this->_model->getCustomer()); + } } From 57cf6eacf0b9808279721d1c48be92bd7719f872 Mon Sep 17 00:00:00 2001 From: Andrew Chorniy <a.chorniy@atwix.com> Date: Wed, 22 Jan 2020 15:04:17 +0200 Subject: [PATCH 227/666] Delete wrongly added type for variable --- app/code/Magento/Customer/Model/Data/Customer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Data/Customer.php b/app/code/Magento/Customer/Model/Data/Customer.php index 27a82d7f8d8f3..5c1fee5ee5633 100644 --- a/app/code/Magento/Customer/Model/Data/Customer.php +++ b/app/code/Magento/Customer/Model/Data/Customer.php @@ -94,7 +94,7 @@ public function getCreatedAt() */ public function getCreatedIn() { - return (string)$this->_get(self::CREATED_IN); + return $this->_get(self::CREATED_IN); } /** From 39ecd070fa0519c7b93962c023703a95829a6630 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 22 Jan 2020 16:10:17 +0200 Subject: [PATCH 228/666] Fixing the disabled currency inputs --- .../CurrencySymbol/view/adminhtml/templates/grid.phtml | 3 ++- .../CurrencySymbol/view/adminhtml/web/js/symbols-form.js | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 397c2598dc3b0..74268f6e4c4de 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -22,7 +22,8 @@ class="required-entry admin__control-text <?= $data['inherited'] ? 'disabled' : '' ?>" type="text" value="<?= $block->escapeHtmlAttr($data['displaySymbol']) ?>" - name="custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> + name="custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]" + <?= $data['inherited'] ? 'disabled' : '' ?>> <div class="admin__field admin__field-option"> <input id="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>" class="admin__control-checkbox" type="checkbox" diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js b/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js index 68f914ddb1b4d..a2cbfa883554a 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/web/js/symbols-form.js @@ -25,12 +25,10 @@ define([ input = $('#custom_currency_symbol' + code); if (checkbox.is(':checked')) { - input.addClass('disabled'); input.val(value); - input.prop('readonly', true); + input.prop('disabled', true); } else { - input.removeClass('disabled'); - input.prop('readonly', false); + input.prop('disabled', false); } } From a071b25012c4132442501b1b58d40dbe3de5dd83 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 22 Jan 2020 16:13:53 +0200 Subject: [PATCH 229/666] magento/magento2#: Remove a redundant call to DB for guest session --- .../Customer/Test/Unit/Model/SessionTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php b/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php index 00f376c4b81bc..03232938cde47 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/SessionTest.php @@ -18,13 +18,15 @@ use Magento\Framework\App\Response\Http; use Magento\Framework\Event\ManagerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\Url; use Magento\Framework\UrlFactory; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class SessionTest extends \PHPUnit\Framework\TestCase +class SessionTest extends TestCase { /** * @var ResourceCustomer|MockObject @@ -85,11 +87,11 @@ protected function setUp() $this->urlFactoryMock = $this->createMock(UrlFactory::class); $this->customerFactoryMock = $this->getMockBuilder(CustomerFactory::class) ->disableOriginalConstructor() - ->setMethods(['create']) + ->setMethods(['create', 'save']) ->getMock(); $this->_customerResourceMock = $this->getMockBuilder(ResourceCustomer::class) ->disableOriginalConstructor() - ->setMethods(['load']) + ->setMethods(['load', 'save']) ->getMock(); $this->customerRepositoryMock = $this->createMock(CustomerRepositoryInterface::class); $helper = new ObjectManagerHelper($this); @@ -164,7 +166,7 @@ public function testSetCustomerDataAsLoggedIn() */ public function testAuthenticate() { - $urlMock = $this->createMock(\Magento\Framework\Url::class); + $urlMock = $this->createMock(Url::class); $urlMock->expects($this->exactly(2)) ->method('getUrl') ->willReturn(''); @@ -216,15 +218,12 @@ protected function prepareLoginDataMock($customerId) $customerMock = $this->createPartialMock( Customer::class, - ['getId', 'isConfirmationRequired', 'getConfirmation', 'updateData', 'getGroupId'] + ['getId', 'getConfirmation', 'updateData', 'getGroupId'] ); - $customerMock->expects($this->once()) + $customerMock->expects($this->exactly(3)) ->method('getId') ->will($this->returnValue($customerId)); $customerMock->expects($this->once()) - ->method('isConfirmationRequired') - ->will($this->returnValue(true)); - $customerMock->expects($this->never()) ->method('getConfirmation') ->will($this->returnValue($customerId)); @@ -290,6 +289,7 @@ public function testSetCustomerRemovesFlagThatShowsIfCustomerIsEmulated() $this->_storageMock->expects($this->once())->method('unsIsCustomerEmulated'); $this->_model->setCustomer($customerMock); } + /** * Test "getCustomer()" for guest user * From df37523bd44a63fe3c220677bf7a5d6ed310b268 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Wed, 22 Jan 2020 16:25:08 +0200 Subject: [PATCH 230/666] #26314: removed default value for parameter --- app/code/Magento/Msrp/view/base/web/js/msrp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c3d9677404f31..db407fbb22ce0 100644 --- a/app/code/Magento/Msrp/view/base/web/js/msrp.js +++ b/app/code/Magento/Msrp/view/base/web/js/msrp.js @@ -301,7 +301,7 @@ define([ * @param {Object} prices * @param {Object|undefined} $priceBox */ - onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices, $priceBox = undefined) { + onUpdateMsrpPrice: function onUpdateMsrpPrice(event, priceIndex, prices, $priceBox) { var defaultMsrp, defaultPrice, From 8a96c5884a3cf62d26a49be4ff94b10423aeb0f9 Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <oroskodias@users.noreply.github.com> Date: Wed, 22 Jan 2020 16:29:58 +0200 Subject: [PATCH 231/666] Extend exception message in Redirect Class --- .../Store/Controller/Store/Redirect.php | 2 +- .../Unit/Controller/Store/RedirectTest.php | 280 ++++++++++++++++++ .../HttpRequestValidator/StoreValidator.php | 2 +- .../Test/Unit/StoreValidatorTest.php | 146 +++++++++ 4 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php create mode 100644 app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php diff --git a/app/code/Magento/Store/Controller/Store/Redirect.php b/app/code/Magento/Store/Controller/Store/Redirect.php index 5d61275e72a28..2cc8ba1905442 100644 --- a/app/code/Magento/Store/Controller/Store/Redirect.php +++ b/app/code/Magento/Store/Controller/Store/Redirect.php @@ -98,7 +98,7 @@ public function execute() /** @var Store $fromStore */ $fromStore = $this->storeRepository->get($fromStoreCode); } catch (NoSuchEntityException $e) { - $error = __('Requested store is not found'); + $error = __("Requested store is not found ({$fromStoreCode})"); } if ($error !== null) { diff --git a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php new file mode 100644 index 0000000000000..7d60fcac24ec9 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -0,0 +1,280 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Store\Test\Unit\Controller\Store; + +use Magento\Framework\App\ActionInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Response\RedirectInterface; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Session\SidResolverInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\Store\Api\StoreResolverInterface; +use Magento\Store\Controller\Store\Redirect; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreResolver; +use Magento\Store\Model\StoreSwitcher\HashGenerator; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test class for redirect controller + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class RedirectTest extends TestCase +{ + private const DEFAULT_STORE_VIEW_CODE = 'default'; + private const STORE_CODE = 'sv1'; + + /** + * @var StoreRepositoryInterface|MockObject + */ + private $storeRepositoryMock; + + /** + * @var RequestInterface|MockObject + */ + private $requestMock; + + /** + * @var StoreResolverInterface|MockObject + */ + private $storeResolverMock; + + /** + * @var RedirectInterface|MockObject + */ + private $redirectMock; + + /** + * @var ResponseInterface|MockObject + */ + private $responseMock; + + /** + * @var ManagerInterface|MockObject + */ + private $messageManagerMock; + + /** + * @var Store|MockObject + */ + private $formStoreMock; + + /** + * @var Store|MockObject + */ + private $currentStoreMock; + + /** + * @var SidResolverInterface|MockObject + */ + private $sidResolverMock; + + /** + * @var HashGenerator|MockObject + */ + private $hashGeneratorMock; + + /** + * @var Redirect + */ + private $redirectController; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->requestMock = $this->createMock(RequestInterface::class); + $this->redirectMock = $this->createMock(RedirectInterface::class); + $this->storeResolverMock = $this->createMock(StoreResolverInterface::class); + $this->storeRepositoryMock = $this->createMock(StoreRepositoryInterface::class); + $this->messageManagerMock = $this->createMock(ManagerInterface::class); + $this->responseMock = $this->createMock(ResponseInterface::class); + $this->formStoreMock = $this->createMock(Store::class); + $this->sidResolverMock = $this->createMock(SidResolverInterface::class); + $this->hashGeneratorMock = $this->createMock(HashGenerator::class); + + $this->currentStoreMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getBaseUrl']) + ->getMock(); + $this->storeRepositoryMock + ->expects($this->once()) + ->method('getById') + ->willReturn($this->currentStoreMock); + $this->storeResolverMock + ->expects($this->once()) + ->method('getCurrentStoreId') + ->willReturnSelf(); + + $objectManager = new ObjectManagerHelper($this); + + $this->redirectController = $objectManager->getObject( + Redirect::class, + [ + 'storeRepository' => $this->storeRepositoryMock, + 'storeResolver' => $this->storeResolverMock, + 'messageManager' => $this->messageManagerMock, + '_request' => $this->requestMock, + '_redirect' => $this->redirectMock, + '_response' => $this->responseMock, + 'sidResolver' => $this->sidResolverMock, + 'hashGenerator' => $this->hashGeneratorMock + ] + ); + } + + /** + * Verify redirect controller + * + * @param string $defaultStoreViewCode + * @param string $storeCode + * + * @dataProvider getConfigDataProvider + * @return void + * @throws NoSuchEntityException + */ + public function testRedirect(string $defaultStoreViewCode, string $storeCode): void + { + $this->requestMock + ->expects($this->at(0)) + ->method('getParam') + ->with(StoreResolver::PARAM_NAME) + ->willReturn($storeCode); + $this->requestMock + ->expects($this->at(1)) + ->method('getParam') + ->with('___from_store') + ->willReturn($defaultStoreViewCode); + $this->requestMock + ->expects($this->at(2)) + ->method('getParam') + ->with(ActionInterface::PARAM_NAME_URL_ENCODED) + ->willReturn($defaultStoreViewCode); + $this->storeRepositoryMock + ->expects($this->once()) + ->method('get') + ->with($defaultStoreViewCode) + ->willReturn($this->formStoreMock); + $this->formStoreMock + ->expects($this->once()) + ->method('getCode') + ->willReturnSelf(); + $this->sidResolverMock + ->expects($this->once()) + ->method('getUseSessionInUrl') + ->willReturn(false); + $this->hashGeneratorMock + ->expects($this->once()) + ->method('generateHash') + ->with($this->formStoreMock) + ->willReturn([]); + + $this->redirectMock + ->expects($this->once()) + ->method('redirect') + ->with( + $this->responseMock, + 'stores/store/switch', + ['_nosid' => true, + '_query' => [ + 'uenc' => $defaultStoreViewCode, + '___from_store' => $this->formStoreMock, + '___store' => $storeCode + ] + ] + ) + ->willReturnSelf(); + + $this->assertEquals(null, $this->redirectController->execute()); + } + + /** + * Verify execute with exception + * + * @param string $defaultStoreViewCode + * @param string $storeCode + * @return void + * @dataProvider getConfigDataProvider + * @throws NoSuchEntityException + */ + public function testRedirectWithThrowsException(string $defaultStoreViewCode, string $storeCode): void + { + $this->requestMock + ->expects($this->at(0)) + ->method('getParam') + ->with(StoreResolver::PARAM_NAME) + ->willReturn($storeCode); + $this->requestMock + ->expects($this->at(1)) + ->method('getParam') + ->with('___from_store') + ->willReturn($defaultStoreViewCode); + $this->storeRepositoryMock + ->expects($this->once()) + ->method('get') + ->with($defaultStoreViewCode) + ->willThrowException(new NoSuchEntityException()); + $this->messageManagerMock + ->expects($this->once()) + ->method('addErrorMessage') + ->willReturnSelf(); + $this->currentStoreMock + ->expects($this->once()) + ->method('getBaseUrl') + ->willReturnSelf(); + $this->redirectMock + ->expects($this->once()) + ->method('redirect') + ->with($this->responseMock, $this->currentStoreMock) + ->willReturnSelf(); + + $this->assertEquals(null, $this->redirectController->execute()); + } + + /** + * Verify redirect target is null + * + * @return void + * @throws NoSuchEntityException + */ + public function testRedirectTargetIsNull(): void + { + $this->requestMock + ->expects($this->at(0)) + ->method('getParam') + ->with(StoreResolver::PARAM_NAME) + ->willReturn(null); + $this->requestMock + ->expects($this->at(1)) + ->method('getParam') + ->with('___from_store') + ->willReturnSelf(); + $this->storeRepositoryMock + ->expects($this->never()) + ->method('get'); + + $this->assertEquals($this->responseMock, $this->redirectController->execute()); + } + + /** + * @inheritDoc + * + * @return array + */ + public function getConfigDataProvider(): array + { + return [ + [ self::DEFAULT_STORE_VIEW_CODE, self::STORE_CODE ] + ]; + } +} diff --git a/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php index 5d0a4edd44b73..8011960915726 100644 --- a/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php +++ b/app/code/Magento/StoreGraphQl/Controller/HttpRequestValidator/StoreValidator.php @@ -45,7 +45,7 @@ public function validate(HttpRequestInterface $request): void $storeCode = trim($headerValue); if (!$this->isStoreActive($storeCode)) { $this->storeManager->setCurrentStore(null); - throw new GraphQlInputException(__('Requested store is not found')); + throw new GraphQlInputException(__('Requested store is not found ({$storeCode})')); } } } diff --git a/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php b/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php new file mode 100644 index 0000000000000..aa160bd3eb8e7 --- /dev/null +++ b/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\StoreGraphQl\Test\Unit; + +use Magento\Framework\App\HttpRequestInterface; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Store\Model\StoreManagerInterface; +use Magento\StoreGraphQl\Controller\HttpRequestValidator\StoreValidator; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test for StoreValidator class + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class StoreValidatorTest extends TestCase +{ + private const DEFAULT_STORE_VIEW_CODE = 'default'; + private const STORE_CODE = 'sv1'; + + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManagerMock; + + /** + * @var HttpRequestInterface|MockObject + */ + private $requestMock; + + /** + * @var StoreValidator + */ + private $storeValidator; + + /** + * @inheritDoc + */ + public function setUp() + { + $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); + $this->requestMock = $this->getMockBuilder(HttpRequestInterface::class) + ->disableOriginalConstructor() + ->setMethods( + [ + 'isPost', + 'isGet', + 'isPatch', + 'isDelete', + 'isPut', + 'isAjax', + 'getHeader' + ] + ) + ->getMock(); + + $objectManager = new ObjectManagerHelper($this); + + $this->storeValidator = $objectManager->getObject( + StoreValidator::class, + [ + 'storeManager' => $this->storeManagerMock + ] + ); + } + + /** + * Verify validate + * + * @param array $config + * + * @dataProvider getConfigDataProvider + * @throws GraphQlInputException + */ + public function testValidate(array $config): void + { + $this->requestMock + ->expects($this->once()) + ->method('getHeader') + ->with('Store') + ->willReturn($config['store']); + $this->storeManagerMock + ->expects($this->once()) + ->method('getStores') + ->with(false, true) + ->willReturn($config['store']); + $this->storeManagerMock + ->expects($this->once()) + ->method('setCurrentStore') + ->with(null) + ->willReturnSelf(); + $this->expectExceptionMessage('Requested store is not found ({$storeCode})'); + $this->storeValidator->validate($this->requestMock); + } + + /** + * Verify validate with active store + * + * @param array $config + * + * @throws GraphQlInputException + * @dataProvider getConfigDataProvider + */ + public function testValidateWithStoreActive(array $config): void + { + $this->requestMock + ->expects($this->once()) + ->method('getHeader') + ->with('Store') + ->willReturn($config['default']); + $this->storeManagerMock + ->expects($this->once()) + ->method('getStores') + ->with(false, true) + ->willReturn($config['default']); + $this->storeManagerMock + ->expects($this->never()) + ->method('setCurrentStore') + ->with(null) + ->willReturnSelf(); + $this->storeValidator->validate($this->requestMock); + } + + /** + * @inheritDoc + * + * @return array + */ + public function getConfigDataProvider(): array + { + return [ + [ + [ + 'default' => self::DEFAULT_STORE_VIEW_CODE, + 'store' => self::STORE_CODE + ] + ] + ]; + } +} From 1e827779044ecf3d91e53e680bf473047533a774 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 22 Jan 2020 16:37:27 +0200 Subject: [PATCH 232/666] Refactor by review comment --- .../Magento/Store/Test/Unit/Controller/Store/RedirectTest.php | 1 + 1 file changed, 1 insertion(+) 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 7d60fcac24ec9..1136194fc322a 100644 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -227,6 +227,7 @@ public function testRedirectWithThrowsException(string $defaultStoreViewCode, st $this->messageManagerMock ->expects($this->once()) ->method('addErrorMessage') + ->with("Requested store is not found ({$defaultStoreViewCode})") ->willReturnSelf(); $this->currentStoreMock ->expects($this->once()) From 4ce3e07e72d50ce0468b75c871f9f5e24bfd6157 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 22 Jan 2020 16:47:52 +0200 Subject: [PATCH 233/666] Fixing static tests --- .../CurrencySymbol/view/adminhtml/templates/grid.phtml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 74268f6e4c4de..9298f0d3ce1d8 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -12,7 +12,7 @@ <form id="currency-symbols-form" action="<?= $block->escapeUrl($block->getFormActionUrl()) ?>" method="post"> <input name="form_key" type="hidden" value="<?= $block->escapeHtmlAttr($block->getFormKey()) ?>" /> <fieldset class="admin__fieldset"> - <?php foreach ($block->getCurrencySymbolsData() as $code => $data) : ?> + <?php foreach ($block->getCurrencySymbolsData() as $code => $data): ?> <div class="admin__field _required"> <label class="admin__field-label" for="custom_currency_symbol<?= $block->escapeHtmlAttr($code) ?>"> <span><?= $block->escapeHtml($code) ?> (<?= $block->escapeHtml($data['displayName']) ?>)</span> @@ -25,9 +25,13 @@ name="custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]" <?= $data['inherited'] ? 'disabled' : '' ?>> <div class="admin__field admin__field-option"> + <?php + $escapedCode = $block->escapeHtmlAttr($block->escapeJs($code)); + $escapedSymbol = $block->escapeJs($data['parentSymbol']); + ?> <input id="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>" class="admin__control-checkbox" type="checkbox" - onclick="toggleUseDefault(<?= '\'' . $block->escapeHtmlAttr($block->escapeJs($code)) . '\',\'' . $block->escapeJs($data['parentSymbol']) . '\'' ?>)" + onclick="toggleUseDefault(<?= '\'' . $escapedCode . '\',\'' . $escapedSymbol . '\'' ?>)" <?= $data['inherited'] ? ' checked="checked"' : '' ?> value="1" name="inherit_custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> From 52b184ed9fe1d54400a0758c8a1f1267177ecfb8 Mon Sep 17 00:00:00 2001 From: Andrew Chorniy <a.chorniy@atwix.com> Date: Wed, 22 Jan 2020 18:15:51 +0200 Subject: [PATCH 234/666] Fixed issues after code sniffer --- app/code/Magento/Customer/Model/Data/Customer.php | 11 +++++++---- .../Customer/Test/Unit/Model/Data/CustomerTest.php | 13 ++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Customer/Model/Data/Customer.php b/app/code/Magento/Customer/Model/Data/Customer.php index 5c1fee5ee5633..f4318d68f6aa4 100644 --- a/app/code/Magento/Customer/Model/Data/Customer.php +++ b/app/code/Magento/Customer/Model/Data/Customer.php @@ -9,7 +9,8 @@ use \Magento\Framework\Api\AttributeValueFactory; /** - * Class Customer + * Customer data model + * * @SuppressWarnings(PHPMD.ExcessivePublicCount) */ class Customer extends \Magento\Framework\Api\AbstractExtensibleObject implements @@ -39,7 +40,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function getCustomAttributesCodes() { @@ -50,6 +51,8 @@ protected function getCustomAttributesCodes() } /** + * Get default billing address id + * * @return string|null */ public function getDefaultBilling() @@ -489,7 +492,7 @@ public function setDisableAutoGroupChange($disableAutoGroupChange) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Customer\Api\Data\CustomerExtensionInterface|null */ @@ -499,7 +502,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Customer\Api\Data\CustomerExtensionInterface $extensionAttributes * @return $this diff --git a/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php index 945f213d015bd..395967c46ae67 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Data/CustomerTest.php @@ -1,4 +1,8 @@ <?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ namespace Magento\Customer\Test\Unit\Model\Data; @@ -45,12 +49,15 @@ public function testGetGroupId() * @dataProvider getCreatedInDataProvider * * @return void - */ + */ public function testGetCreatedIn($options, $expectedResult) { - for ($i = 0; $i < count($options); $i++) { + $optionsCount = count($options); + $expectedCount = count($expectedResult); + + for ($i = 0; $i < $optionsCount; $i++) { $this->model->setCreatedIn($options[$i]); - for ($j = $i; $j < count($expectedResult); $j++) { + for ($j = $i; $j < $expectedCount; $j++) { $this->assertEquals($expectedResult[$j], $this->model->getCreatedIn()); break; } From 3b629811c14c613b8b0f962dd0cb3a517cc914bf Mon Sep 17 00:00:00 2001 From: Prabhu Ram <pganapat@adobe.com> Date: Wed, 22 Jan 2020 10:48:27 -0600 Subject: [PATCH 235/666] MC-24172: Fix Skipped MFTF Tests From MC-17140: MC-14770, MC-14771, MC-14772 - unskipping MC-24172 --- .../ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index 67a2551ff239b..02d6d90ae5d0e 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -17,9 +17,6 @@ <testCaseId value="MC-14770"/> <group value="CatalogRule"/> <group value="mtf_migrated"/> - <skip> - <issueId value="MC-24172"/> - </skip> </annotations> <before> <!-- Login as Admin --> From c9d5e8ef8e3b12f6483ec02e2bf561c2752b68d1 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Wed, 22 Jan 2020 22:46:44 +0530 Subject: [PATCH 236/666] Error message to becached for grid data storage component --- app/code/Magento/Ui/view/base/web/js/grid/data-storage.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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; From 87842d3d34e74f6102ec5f39c62fe6e23aa5761e Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Wed, 22 Jan 2020 19:58:42 +0100 Subject: [PATCH 237/666] #26065 unit test improve --- .../Model/Product/Type/Configurable.php | 9 +++++---- .../Test/Unit/Model/Product/Type/ConfigurableTest.php | 10 ++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 36981aafc34e2..fa677b0b8b421 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -592,7 +592,7 @@ protected function getGalleryReadHandler() * @param \Magento\Catalog\Model\Product $product * @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection */ - public function getLinkedProductCollection($product) + protected function getLinkedProductCollection($product) { $collection = $this->_productCollectionFactory->create()->setFlag( 'product_children', @@ -767,8 +767,9 @@ public function isSalable($product) $storeId = $storeId->getId(); } - if (isset($this->isSaleableBySku[$storeId][$product->getSku()])) { - return $this->isSaleableBySku[$storeId][$product->getSku()]; + $sku = $product->getSku(); + if (isset($this->isSaleableBySku[$storeId][$sku])) { + return $this->isSaleableBySku[$storeId][$sku]; } $salable = parent::isSalable($product); @@ -780,7 +781,7 @@ public function isSalable($product) $salable = 0 !== $collection->getSize(); } - $this->isSaleableBySku[$storeId][$product->getSku()] = $salable; + $this->isSaleableBySku[$storeId][$sku] = $salable; return $salable; } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php index 165e479d99348..603b5b4c90f46 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php @@ -567,12 +567,18 @@ public function testHasOptionsFalse() public function testIsSalable() { $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->setMethods(['__wakeup', 'getStatus', 'hasData', 'getData', 'getStoreId', 'setData']) + ->setMethods(['__wakeup', 'getStatus', 'hasData', 'getData', 'getStoreId', 'setData', 'getSku']) ->disableOriginalConstructor() ->getMock(); + $productMock + ->expects($this->at(0)) + ->method('getData') + ->with('_cache_instance_store_filter') + ->willReturn(0); $productMock->expects($this->once())->method('getStatus')->willReturn(1); $productMock->expects($this->any())->method('hasData')->willReturn(true); - $productMock->expects($this->at(2))->method('getData')->with('is_salable')->willReturn(true); + $productMock->expects($this->at(1))->method('getSku')->willReturn('SKU-CODE'); + $productMock->expects($this->at(4))->method('getData')->with('is_salable')->willReturn(true); $productCollection = $this->getMockBuilder( \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection::class ) From 980f7c3788cddba48d9deae6c6ab29e5340d5ea6 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@gmail.com> Date: Thu, 23 Jan 2020 08:17:36 +0200 Subject: [PATCH 238/666] MC-29047: Fix MFTF test --- ...tCheckCategorySimpleProductActionGroup.xml | 2 - ...urableProductCategoryViewChildOnlyTest.xml | 129 ------------------ 2 files changed, 131 deletions(-) delete mode 100644 app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml index ef8d5e3a1212a..b8bc3197d1a11 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontCheckCategorySimpleProductActionGroup.xml @@ -19,9 +19,7 @@ <waitForElementVisible selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="waitForProduct"/> <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName(product.name)}}" stepKey="assertProductName"/> <see userInput="${{product.price}}.00" selector="{{StorefrontCategoryProductSection.ProductPriceByName(product.name)}}" stepKey="AssertProductPrice"/> - <!-- @TODO: MAGETWO-80272 Move to Magento_Checkout --> <moveMouseOver selector="{{StorefrontCategoryProductSection.ProductInfoByName(product.name)}}" stepKey="moveMouseOverProduct"/> - <!-- @TODO: MAGETWO-80272 Move to Magento_Checkout --> <seeElement selector="{{StorefrontCategoryProductSection.ProductAddToCartByName(product.name)}}" stepKey="AssertAddToCart"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml deleted file mode 100644 index 6c9b985bf38f7..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml +++ /dev/null @@ -1,129 +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="StorefrontConfigurableProductCategoryViewChildOnlyTest"> - <annotations> - <features value="ConfigurableProduct"/> - <stories value="View configurable product child in storefront"/> - <title value="DEPRECATED It should be possible to only view the child product of a configurable product"/> - <description value="Create configurable product, add to category such that only child variation is visible in category"/> - <severity value="CRITICAL"/> - <testCaseId value="MC-5832"/> - <group value="ConfigurableProduct"/> - <skip> - <issueId value="DEPRECATED">Use StorefrontShouldSeeOnlyConfigurableProductChildAssignedToSeparateCategoryTest instead</issueId> - </skip> - </annotations> - <before> - <!-- Create the category --> - <createData entity="ApiCategory" stepKey="createCategory"/> - <createData entity="ApiCategory" stepKey="secondCategory"/> - - <!-- Create an attribute with two options to be used in the first child product --> - <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Add the attribute we just created to default attribute set --> - <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </createData> - - <!-- Get the first option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Get the second option of the attribute we created --> - <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - </getData> - - <!-- Create the configurable product and add it to the category --> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> - <requiredEntity createDataKey="createCategory"/> - </createData> - - <!-- Create a simple product and give it the attribute with the first option --> - <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - </createData> - - <!-- Create a simple product and give it the attribute with the second option --> - <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption2"/> - </createData> - - <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> - <requiredEntity createDataKey="getConfigAttributeOption1"/> - <requiredEntity createDataKey="getConfigAttributeOption2"/> - </createData> - - <!-- Add the first simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct1"/> - </createData> - - <!-- Add the second simple product to the configurable product --> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigChildProduct2"/> - </createData> - </before> - - <after> - <actionGroup ref="logout" stepKey="adminLogout"/> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> - <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> - <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> - </after> - - <actionGroup ref="LoginAsAdmin" stepKey="login"/> - - <!-- Go to the product page for the first product --> - <amOnPage stepKey="goToProductGrid" url="{{ProductCatalogPage.url}}"/> - <waitForPageLoad stepKey="waitForProductGridLoad"/> - <actionGroup stepKey="searchForSimpleProduct" ref="FilterProductGridBySku2ActionGroup"> - <argument name="sku" value="$$createConfigChildProduct1.sku$$"/> - </actionGroup> - <actionGroup stepKey="openProductEditPage" ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup"/> - <!-- Edit the visibility the first simple product --> - <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="Catalog, Search" stepKey="selectVisibilityCatalogSearch"/> - <!--Add to category--> - <searchAndMultiSelectOption selector="{{AdminProductFormSection.categoriesDropdown}}" parameterArray="[$$secondCategory.name$$]" stepKey="addProductToCategory"/> - <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct"/> - <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="assertSaveMessageSuccess"/> - - <!-- Go to storefront to view child product --> - <amOnPage stepKey="goToStoreFront" url="{{StorefrontHomePage.url}}"/> - <waitForPageLoad stepKey="waitForStorefront"/> - <click selector="{{StorefrontHeaderSection.NavigationCategoryByName($$secondCategory.name$$)}}" stepKey="goToCategoryStorefront"/> - <waitForPageLoad stepKey="waitForStorefrontCategory"/> - <seeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct1.name$$)}}" stepKey="seeChildProductInCategory"/> - <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct2.name$$)}}" stepKey="dontSeeOtherChildProduct"/> - <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigProduct.name$$)}}" stepKey="dontSeeParentProduct"/> - <click selector="{{StorefrontCategoryProductSection.ProductTitleByName($$createConfigChildProduct1.name$$)}}" stepKey="clickProductName"/> - <waitForPageLoad stepKey="waitForProductPageLoad"/> - <seeInCurrentUrl url="$$createConfigChildProduct1.custom_attributes[url_key]$$" stepKey="seeProductPageIsAccessible"/> - <seeElement selector="{{StorefrontProductInfoMainSection.productName($$createConfigChildProduct1.name$$)}}" stepKey="seeProductNameOnProductPage"/> - </test> -</tests> From f165a5375830077ebaed7d07f7d8c965332ffae9 Mon Sep 17 00:00:00 2001 From: Deepak S Nair <deepak.nair@ranosys.com> Date: Thu, 23 Jan 2020 11:51:32 +0530 Subject: [PATCH 239/666] fixed #25761 - added automated test cases --- .../Unit/Model/ItemProvider/StoreUrlTest.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php new file mode 100644 index 0000000000000..6a6d2a5770439 --- /dev/null +++ b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sitemap\Test\Unit\Model\ItemProvider; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sitemap\Model\ItemProvider\ConfigReaderInterface; +use Magento\Sitemap\Model\ItemProvider\StoreUrl as StoreUrlItemResolver; +use Magento\Sitemap\Model\SitemapItem; +use Magento\Sitemap\Model\SitemapItemInterfaceFactory; + +class StoreUrlTest extends \PHPUnit\Framework\TestCase +{ + /** + * test for getItems method + */ + public function testGetItems() + { + $configReaderMock = $this->getConfigReaderMock(); + $itemFactoryMock = $this->getItemFactoryMock(); + $resolver = new StoreUrlItemResolver($configReaderMock, $itemFactoryMock); + $items = $resolver->getItems(1); + + $this->assertTrue(count($items) == 1); + foreach ($items as $index => $item) { + $this->assertSame('daily', $items[$index]->getChangeFrequency()); + $this->assertSame('1.0', $items[$index]->getPriority()); + } + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getItemFactoryMock() + { + $itemFactoryMock = $this->getMockBuilder(SitemapItemInterfaceFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $itemFactoryMock->expects($this->any()) + ->method('create') + ->willReturnCallback(function ($data) { + $helper = new ObjectManager($this); + + return $helper->getObject(SitemapItem::class, $data); + }); + + return $itemFactoryMock; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getConfigReaderMock() + { + $configReaderMock = $this->getMockForAbstractClass(ConfigReaderInterface::class); + $configReaderMock->expects($this->any()) + ->method('getPriority') + ->willReturn('1.0'); + $configReaderMock->expects($this->any()) + ->method('getChangeFrequency') + ->willReturn('daily'); + + return $configReaderMock; + } +} \ No newline at end of file From 69d07c13b394bdf367048ba25dbf922f7cc4f1b6 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Thu, 23 Jan 2020 10:09:29 +0200 Subject: [PATCH 240/666] #18012: improved cases for DataProviderTest --- .../Test/Unit/Model/Js/DataProviderTest.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) 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 b5bfbbc29a603..56cfcad7a2775 100644 --- a/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php +++ b/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php @@ -105,24 +105,31 @@ public function testGetData() 'hello1' => 'hello1translated', 'hello2' => 'hello2translated', 'hello3' => 'hello3translated', - 'hello4' => 'hello4translated' + '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', // this value should be last after running data provider - 'content2$.mage.__("hello3")content3', + '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'] + [['hello4'], [], 'hello4translated'], + [['ko i18'], [], 'ko i18 translated'], + [['underscore i18'], [], 'underscore i18 translated'], ]; - $patterns = ['~\$\.mage\.__\(([\'"])(.+?)\1\)~']; + $patterns = [ + '~\$\.mage\.__\(([\'"])(.+?)\1\)~', + '~(?:i18n\:|_\.i18n\()\s*(["\'])(.*?)(?<!\\\\)\1~', + ]; $this->appStateMock->expects($this->once()) ->method('getAreaCode') From ea1c1cdf5548ecea506e46b20ab479498719ba74 Mon Sep 17 00:00:00 2001 From: Andrii Kalinich <51681435+engcom-Echo@users.noreply.github.com> Date: Thu, 23 Jan 2020 10:18:22 +0200 Subject: [PATCH 241/666] Update StoreValidatorTest.php --- app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php b/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php index aa160bd3eb8e7..7a4ea46990e00 100644 --- a/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php +++ b/app/code/Magento/StoreGraphQl/Test/Unit/StoreValidatorTest.php @@ -128,7 +128,7 @@ public function testValidateWithStoreActive(array $config): void } /** - * @inheritDoc + * Data provider * * @return array */ From a62180759f0179e7d76766e0d6c3324b50aecdd1 Mon Sep 17 00:00:00 2001 From: Andrii Kalinich <51681435+engcom-Echo@users.noreply.github.com> Date: Thu, 23 Jan 2020 10:18:51 +0200 Subject: [PATCH 242/666] Update RedirectTest.php --- .../Magento/Store/Test/Unit/Controller/Store/RedirectTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1136194fc322a..3943b84841806 100644 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -268,7 +268,7 @@ public function testRedirectTargetIsNull(): void } /** - * @inheritDoc + * Data provider * * @return array */ From 8f5b2c7ff88d4771ad34bd0548185d3cc0c30643 Mon Sep 17 00:00:00 2001 From: Deepak S Nair <deepak.nair@ranosys.com> Date: Thu, 23 Jan 2020 14:33:12 +0530 Subject: [PATCH 243/666] fixed #25761 - update test case and one comment --- app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php | 2 +- .../Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php index dd7c50385945f..e262f56d0905f 100644 --- a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php @@ -25,7 +25,7 @@ class StoreUrl implements ItemProviderInterface private $configReader; /** - * CategorySitemapItemResolver constructor. + * StoreUrlSitemapItemResolver constructor. * * @param ConfigReaderInterface $configReader * @param SitemapItemInterfaceFactory $itemFactory diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php index 6a6d2a5770439..62b30aa176bf1 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php @@ -25,9 +25,9 @@ public function testGetItems() $items = $resolver->getItems(1); $this->assertTrue(count($items) == 1); - foreach ($items as $index => $item) { - $this->assertSame('daily', $items[$index]->getChangeFrequency()); - $this->assertSame('1.0', $items[$index]->getPriority()); + foreach ($items as $item) { + $this->assertSame('daily', $item->getChangeFrequency()); + $this->assertSame('1.0', $item->getPriority()); } } From 58adcc59e675430e890ab5d18f675e90715646a1 Mon Sep 17 00:00:00 2001 From: Vaha <vaha@atwix.com> Date: Thu, 23 Jan 2020 11:31:48 +0200 Subject: [PATCH 244/666] #18012: updated description for DataProviderTest --- .../Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 56cfcad7a2775..146e1c06782ce 100644 --- a/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php +++ b/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php @@ -15,7 +15,7 @@ use Magento\Framework\Phrase\Renderer\Translate; /** - * Class DataProviderTest + * Verify data provider translation * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ From 8e6b0c8530470109678568e44d4d5c7baf087f0b Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Thu, 23 Jan 2020 11:04:24 +0100 Subject: [PATCH 245/666] Add frontend template hints status command after suggestions --- .../Command/TemplateHintsStatusCommand.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 296d5dd7ac82d..d61db01dfd4ee 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -22,7 +22,7 @@ class TemplateHintsStatusCommand extends Command /** * @var ScopeConfigInterface */ - protected $scopeConfig; + private $scopeConfig; /** * Initialize dependencies. @@ -53,12 +53,23 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $templateHintsStatus = - ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) + ($this->isTemplateHintsEnabled()) ? 'enabled' : 'disabled'; $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); $output->writeln("<info>" . $templateHintsMessage . "</info>"); - return 0; + return \Magento\Framework\Console\Cli::RETURN_SUCCESS; + } + + /** + * @return bool + */ + private function isTemplateHintsEnabled() + { + $result = ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) + ? true + : false; + return $result; } } From c4ffa89eea24b3ce906409f176ecd74dad5c57fa Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 23 Jan 2020 12:09:43 +0200 Subject: [PATCH 246/666] Use view model insead of helper, fix static tests --- .../ViewModel/Layer/Filter.php | 41 +++++++++++++++++++ .../catalog_category_view_type_layered.xml | 6 ++- .../frontend/templates/layer/filter.phtml | 18 ++++---- .../templates/product/layered/renderer.phtml | 29 +++++++++---- 4 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 app/code/Magento/LayeredNavigation/ViewModel/Layer/Filter.php diff --git a/app/code/Magento/LayeredNavigation/ViewModel/Layer/Filter.php b/app/code/Magento/LayeredNavigation/ViewModel/Layer/Filter.php new file mode 100644 index 0000000000000..fbfd5d3432d34 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/ViewModel/Layer/Filter.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\LayeredNavigation\ViewModel\Layer; + +use Magento\Catalog\Helper\Data as DataHelper; +use Magento\Framework\View\Element\Block\ArgumentInterface; + +/** + * ViewModel for Product Layer + */ +class Filter implements ArgumentInterface +{ + /** + * @var DataHelper + */ + private $dataHelper; + + /** + * Constructor + * + * @param DataHelper $dataHelper + */ + public function __construct(DataHelper $dataHelper) + { + $this->dataHelper = $dataHelper; + } + + /** + * Check is should display product count on layer + * + * @return bool + */ + public function shouldDisplayProductCountOnLayer(): bool + { + return $this->dataHelper->shouldDisplayProductCountOnLayer(); + } +} diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalog_category_view_type_layered.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalog_category_view_type_layered.xml index 647874540f94c..6f0a1af0f5bae 100644 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalog_category_view_type_layered.xml +++ b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalog_category_view_type_layered.xml @@ -11,7 +11,11 @@ <referenceContainer name="sidebar.main"> <block class="Magento\LayeredNavigation\Block\Navigation\Category" name="catalog.leftnav" before="-" template="Magento_LayeredNavigation::layer/view.phtml"> <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" /> - <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/> + <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"> + <arguments> + <argument name="product_layer_view_model" xsi:type="object">Magento\LayeredNavigation\ViewModel\Layer\Filter</argument> + </arguments> + </block> </block> </referenceContainer> </body> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml b/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml index 7313207ecf663..de81373a11573 100644 --- a/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml +++ b/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml @@ -7,20 +7,18 @@ // phpcs:disable Magento2.Templates.ThisInTemplate.FoundThis ?> <?php -/** - * Template for filter items block - * - * @var $block \Magento\LayeredNavigation\Block\Navigation\FilterRenderer - */ +/** @var $block \Magento\LayeredNavigation\Block\Navigation\FilterRenderer */ +/** @var \Magento\LayeredNavigation\ViewModel\Layer\Filter $viewModel */ +$viewModel = $block->getData('product_layer_view_model'); ?> <ol class="items"> - <?php foreach ($filterItems as $filterItem) : ?> + <?php foreach ($filterItems as $filterItem) :?> <li class="item"> - <?php if ($filterItem->getCount() > 0) : ?> + <?php if ($filterItem->getCount() > 0) :?> <a href="<?= $block->escapeUrl($filterItem->getUrl()) ?>" rel="nofollow"> <?= /* @noEscape */ $filterItem->getLabel() ?> - <?php if ($this->helper(\Magento\Catalog\Helper\Data::class)->shouldDisplayProductCountOnLayer()) : ?> + <?php if ($viewModel->shouldDisplayProductCountOnLayer()) : ?> <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?><span class="filter-count-label"> <?php if ($filterItem->getCount() == 1) : ?> <?= $block->escapeHtml(__('item')) ?><?php @@ -31,11 +29,11 @@ </a> <?php else :?> <?= /* @noEscape */ $filterItem->getLabel() ?> - <?php if ($this->helper(\Magento\Catalog\Helper\Data::class)->shouldDisplayProductCountOnLayer()) : ?> + <?php if ($viewModel->shouldDisplayProductCountOnLayer()) : ?> <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?><span class="filter-count-label"> <?php if ($filterItem->getCount() == 1) : ?><?= $block->escapeHtml(__('items')) ?><?php - else : + else: ?><?= $block->escapeHtml(__('items')) ?><?php endif;?></span></span> <?php endif; ?> diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml index 0680290e25002..5623da147130c 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml @@ -14,11 +14,11 @@ attribute-code="<?= $block->escapeHtmlAttr($swatchData['attribute_code']) ?>" attribute-id="<?= $block->escapeHtmlAttr($swatchData['attribute_id']) ?>"> <div class="swatch-attribute-options clearfix"> - <?php foreach ($swatchData['options'] as $option => $label) : ?> + <?php foreach ($swatchData['options'] as $option => $label) :?> <a href="<?= $block->escapeUrl($label['link']) ?>" rel="nofollow" aria-label="<?= $block->escapeHtmlAttr($label['label']) ?>" class="swatch-option-link-layered"> - <?php if (isset($swatchData['swatches'][$option]['type'])) : ?> + <?php if (isset($swatchData['swatches'][$option]['type'])) :?> <?php switch ($swatchData['swatches'][$option]['type']) { case '3': ?> @@ -33,8 +33,16 @@ <?php break; case '2': ?> - <?php $swatchThumbPath = $block->getSwatchPath('swatch_thumb', $swatchData['swatches'][$option]['value']); ?> - <?php $swatchImagePath = $block->getSwatchPath('swatch_image', $swatchData['swatches'][$option]['value']); ?> + <?php $swatchThumbPath = $block->getSwatchPath( + 'swatch_thumb', + $swatchData['swatches'][$option]['value'] + ); ?> + <?php $swatchImagePath = $block->getSwatchPath( + 'swatch_image', + $swatchData['swatches'][$option]['value'] + ); + $escapedUrl = $block->escapeUrl($swatchImagePath); + ?> <div class="swatch-option image <?= $block->escapeHtmlAttr($label['custom_style']) ?>" tabindex="-1" option-type="2" @@ -42,7 +50,10 @@ option-label="<?= $block->escapeHtmlAttr($label['label']) ?>" option-tooltip-thumb="<?= $block->escapeUrl($swatchThumbPath) ?>" option-tooltip-value="" - style="background: url(<?= $block->escapeUrl($swatchImagePath) ?>) no-repeat center; background-size: initial;"></div> + style="background: url(<?= + $escapedUrl + ?>) no-repeat center; background-size: initial;"> + </div> <?php break; case '1': ?> @@ -52,8 +63,12 @@ option-id="<?= $block->escapeHtmlAttr($option) ?>" option-label="<?= $block->escapeHtmlAttr($label['label']) ?>" option-tooltip-thumb="" - option-tooltip-value="<?= $block->escapeHtmlAttr($swatchData['swatches'][$option]['value']) ?>" - style="background: <?= $block->escapeHtmlAttr($swatchData['swatches'][$option]['value']) ?> no-repeat center; background-size: initial;"></div> + option-tooltip-value="<?= $block->escapeHtmlAttr( + $swatchData['swatches'][$option]['value'] + ) ?>" + style="background: <?= $block->escapeHtmlAttr( + $swatchData['swatches'][$option]['value'] + ) ?> no-repeat center; background-size: initial;"></div> <?php break; case '0': default: From 7d316ecfcb850a60253d897c6dba020f1a8b3a83 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Thu, 23 Jan 2020 12:11:14 +0200 Subject: [PATCH 247/666] Code cleaning --- .../Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php index 23465b1b26a42..a1c461a10abdc 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -6,6 +6,7 @@ namespace Magento\Fedex\Test\Unit\Plugin\Block\Tracking; +use Magento\Fedex\Model\Carrier; use Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Shipping\Block\Tracking\Popup; @@ -44,7 +45,7 @@ public function testAfterFormatDeliveryDateTimeWithFedexCarrier() ->getMock(); $trackingStatusMock->expects($this::once()) ->method('getCarrier') - ->willReturn(\Magento\Fedex\Model\Carrier::CODE); + ->willReturn(Carrier::CODE); /** @var Popup|MockObject $subjectMock */ $subjectMock = $this->getMockBuilder(Popup::class) From c93c1a0d0912202d1e81c6cfcacd15b0d691257e Mon Sep 17 00:00:00 2001 From: Viktor Sevch <svitja@ukr.net> Date: Thu, 23 Jan 2020 12:17:43 +0200 Subject: [PATCH 248/666] MC-23546: Child Configurable product does not save disabled status via API --- .../Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml index 1169d053ec7c8..44a4001f7b579 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/StorefrontQuickSearchConfigurableChildrenTest.xml @@ -15,6 +15,7 @@ <description value="Use Quick Search to find a configurable product with enabled/disable children"/> <severity value="MAJOR"/> <testCaseId value="MC-28374"/> + <useCaseId value="MAGETWO-69181"/> <group value="catalogSearch"/> <group value="mtf_migrated"/> </annotations> From d4cbfaf4a3fa88ca13e7640fce5d08b9d19dba01 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Thu, 23 Jan 2020 11:19:19 +0100 Subject: [PATCH 249/666] Add frontend template hints status command after suggestions --- .../Console/Command/TemplateHintsStatusCommand.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index d61db01dfd4ee..98719784a03c4 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -10,6 +10,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Console\Cli; /** * Command to show frontend template hints status @@ -59,7 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); $output->writeln("<info>" . $templateHintsMessage . "</info>"); - return \Magento\Framework\Console\Cli::RETURN_SUCCESS; + return Cli::RETURN_SUCCESS; } /** @@ -67,9 +68,6 @@ protected function execute(InputInterface $input, OutputInterface $output) */ private function isTemplateHintsEnabled() { - $result = ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')) - ? true - : false; - return $result; + return ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')); } } From 76946a6f62830fe76ae6e5fe0d23bdace40f74ce Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 23 Jan 2020 13:00:00 +0200 Subject: [PATCH 250/666] Static test fix attempt 2 --- .../frontend/templates/layer/filter.phtml | 22 ++++++++------- .../templates/product/layered/renderer.phtml | 28 +++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml b/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml index de81373a11573..6b65d184b462a 100644 --- a/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml +++ b/app/code/Magento/LayeredNavigation/view/frontend/templates/layer/filter.phtml @@ -13,25 +13,27 @@ $viewModel = $block->getData('product_layer_view_model'); ?> <ol class="items"> - <?php foreach ($filterItems as $filterItem) :?> + <?php foreach ($filterItems as $filterItem): ?> <li class="item"> - <?php if ($filterItem->getCount() > 0) :?> + <?php if ($filterItem->getCount() > 0): ?> <a href="<?= $block->escapeUrl($filterItem->getUrl()) ?>" rel="nofollow"> <?= /* @noEscape */ $filterItem->getLabel() ?> - <?php if ($viewModel->shouldDisplayProductCountOnLayer()) : ?> - <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?><span class="filter-count-label"> - <?php if ($filterItem->getCount() == 1) : + <?php if ($viewModel->shouldDisplayProductCountOnLayer()): ?> + <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?> + <span class="filter-count-label"> + <?php if ($filterItem->getCount() == 1): ?> <?= $block->escapeHtml(__('item')) ?><?php - else : + else: ?> <?= $block->escapeHtml(__('item')) ?><?php endif;?></span></span> <?php endif; ?> </a> - <?php else :?> + <?php else: ?> <?= /* @noEscape */ $filterItem->getLabel() ?> - <?php if ($viewModel->shouldDisplayProductCountOnLayer()) : ?> - <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?><span class="filter-count-label"> - <?php if ($filterItem->getCount() == 1) : + <?php if ($viewModel->shouldDisplayProductCountOnLayer()): ?> + <span class="count"><?= /* @noEscape */ (int)$filterItem->getCount() ?> + <span class="filter-count-label"> + <?php if ($filterItem->getCount() == 1): ?><?= $block->escapeHtml(__('items')) ?><?php else: ?><?= $block->escapeHtml(__('items')) ?><?php diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml index 5623da147130c..7cb9b06713ef2 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml @@ -14,11 +14,11 @@ attribute-code="<?= $block->escapeHtmlAttr($swatchData['attribute_code']) ?>" attribute-id="<?= $block->escapeHtmlAttr($swatchData['attribute_id']) ?>"> <div class="swatch-attribute-options clearfix"> - <?php foreach ($swatchData['options'] as $option => $label) :?> + <?php foreach ($swatchData['options'] as $option => $label): ?> <a href="<?= $block->escapeUrl($label['link']) ?>" rel="nofollow" aria-label="<?= $block->escapeHtmlAttr($label['label']) ?>" class="swatch-option-link-layered"> - <?php if (isset($swatchData['swatches'][$option]['type'])) :?> + <?php if (isset($swatchData['swatches'][$option]['type'])): ?> <?php switch ($swatchData['swatches'][$option]['type']) { case '3': ?> @@ -34,14 +34,14 @@ case '2': ?> <?php $swatchThumbPath = $block->getSwatchPath( - 'swatch_thumb', - $swatchData['swatches'][$option]['value'] - ); ?> + 'swatch_thumb', + $swatchData['swatches'][$option]['value'] + ); ?> <?php $swatchImagePath = $block->getSwatchPath( - 'swatch_image', - $swatchData['swatches'][$option]['value'] + 'swatch_image', + $swatchData['swatches'][$option]['value'] ); - $escapedUrl = $block->escapeUrl($swatchImagePath); + $escapedUrl = $block->escapeUrl($swatchImagePath); ?> <div class="swatch-option image <?= $block->escapeHtmlAttr($label['custom_style']) ?>" tabindex="-1" @@ -50,8 +50,8 @@ option-label="<?= $block->escapeHtmlAttr($label['label']) ?>" option-tooltip-thumb="<?= $block->escapeUrl($swatchThumbPath) ?>" option-tooltip-value="" - style="background: url(<?= - $escapedUrl + style="background: url(<?= + /* @noEscape */ $escapedUrl ?>) no-repeat center; background-size: initial;"> </div> <?php break; @@ -64,11 +64,11 @@ option-label="<?= $block->escapeHtmlAttr($label['label']) ?>" option-tooltip-thumb="" option-tooltip-value="<?= $block->escapeHtmlAttr( - $swatchData['swatches'][$option]['value'] - ) ?>" + $swatchData['swatches'][$option]['value'] + ) ?>" style="background: <?= $block->escapeHtmlAttr( - $swatchData['swatches'][$option]['value'] - ) ?> no-repeat center; background-size: initial;"></div> + $swatchData['swatches'][$option]['value'] + ) ?> no-repeat center; background-size: initial;"></div> <?php break; case '0': default: From 61bc535bc277a340fd43bf9722c331b2a08f5712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bajsarowicz?= <lukasz.bajsarowicz@gmail.com> Date: Thu, 23 Jan 2020 13:27:19 +0100 Subject: [PATCH 251/666] Fix: Static tests --- .../Magento/Framework/Autoload/AutoloaderRegistry.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php b/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php index 7a7e3501f89bd..037d8c2181dbf 100644 --- a/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php +++ b/lib/internal/Magento/Framework/Autoload/AutoloaderRegistry.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Autoload; +use InvalidArgumentException; use Magento\Framework\Autoload\AutoloaderInterface; /** @@ -23,7 +24,7 @@ class AutoloaderRegistry * @param AutoloaderInterface $newAutoloader * @return void */ - public static function registerAutoloader(AutoloaderInterface $newAutoloader) + public static function registerAutoloader(AutoloaderInterface $newAutoloader): void { self::$autoloader = $newAutoloader; } @@ -31,13 +32,13 @@ public static function registerAutoloader(AutoloaderInterface $newAutoloader) /** * Returns the registered autoloader * - * @throws \Exception + * @throws InvalidArgumentException * @return AutoloaderInterface */ public static function getAutoloader(): AutoloaderInterface { if (!self::$autoloader instanceof AutoloaderInterface) { - throw new \Exception('Autoloader is not registered, cannot be retrieved.'); + throw new InvalidArgumentException('Autoloader is not registered, cannot be retrieved.'); } return self::$autoloader; From d93fe31aa16a297c28dcba4c5f8ad906475e08f2 Mon Sep 17 00:00:00 2001 From: Deepak S Nair <deepak.nair@ranosys.com> Date: Thu, 23 Jan 2020 18:14:33 +0530 Subject: [PATCH 252/666] fix #25761 - resolved feedbacks --- .../Model/ItemProvider/StoreUrlConfigReader.php | 4 ++-- .../Test/Unit/Model/ItemProvider/StoreUrlTest.php | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php index 9a33028d77c76..782863e79ea4d 100644 --- a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php @@ -36,7 +36,7 @@ public function __construct(ScopeConfigInterface $scopeConfig) } /** - * {@inheritdoc} + * @inheritdoc */ public function getPriority($storeId) { @@ -48,7 +48,7 @@ public function getPriority($storeId) } /** - * {@inheritdoc} + * @inheritdoc */ public function getChangeFrequency($storeId) { diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php index 62b30aa176bf1..e18a54889a1b2 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php @@ -11,8 +11,10 @@ use Magento\Sitemap\Model\ItemProvider\StoreUrl as StoreUrlItemResolver; use Magento\Sitemap\Model\SitemapItem; use Magento\Sitemap\Model\SitemapItemInterfaceFactory; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; -class StoreUrlTest extends \PHPUnit\Framework\TestCase +class StoreUrlTest extends TestCase { /** * test for getItems method @@ -24,7 +26,7 @@ public function testGetItems() $resolver = new StoreUrlItemResolver($configReaderMock, $itemFactoryMock); $items = $resolver->getItems(1); - $this->assertTrue(count($items) == 1); + $this->assertCount(1, $items); foreach ($items as $item) { $this->assertSame('daily', $item->getChangeFrequency()); $this->assertSame('1.0', $item->getPriority()); @@ -32,7 +34,7 @@ public function testGetItems() } /** - * @return \PHPUnit_Framework_MockObject_MockObject + * @return SitemapItemInterfaceFactory|MockObject */ private function getItemFactoryMock() { @@ -53,7 +55,7 @@ private function getItemFactoryMock() } /** - * @return \PHPUnit_Framework_MockObject_MockObject + * @return ConfigReaderInterface|MockObject */ private function getConfigReaderMock() { From 256a84517c8de179c1d9cf4d74e724d256f40a5a Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 23 Jan 2020 15:22:43 +0200 Subject: [PATCH 253/666] Add missing view model --- .../view/frontend/layout/catalogsearch_result_index.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_result_index.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_result_index.xml index 3bb21ed09a01c..28006ca70e07b 100644 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_result_index.xml +++ b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_result_index.xml @@ -11,7 +11,11 @@ <referenceContainer name="sidebar.main"> <block class="Magento\LayeredNavigation\Block\Navigation\Search" name="catalogsearch.leftnav" before="-" template="Magento_LayeredNavigation::layer/view.phtml"> <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalogsearch.navigation.state" as="state" /> - <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalogsearch.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/> + <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalogsearch.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"> + <arguments> + <argument name="product_layer_view_model" xsi:type="object">Magento\LayeredNavigation\ViewModel\Layer\Filter</argument> + </arguments> + </block> </block> </referenceContainer> </body> From f29159f075d136b411693af2be73f76a4a4a413a Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Thu, 23 Jan 2020 15:31:34 +0200 Subject: [PATCH 254/666] MC-30498: Cannot place an order using PayPal through Braintree using sample data customer --- .../view/frontend/web/js/view/payment/method-renderer/paypal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js index ea5200e4ba51f..c0ad38173c52d 100644 --- a/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js +++ b/app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js @@ -269,6 +269,7 @@ define([ */ onError: function () { self.showError($t('Payment ' + self.getTitle() + ' can\'t be initialized')); + self.reInitPayPal(); } }, self.paypalButtonSelector); }, From 63682a05b94d2475ed26c0002d29bd4d9f792b31 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Thu, 23 Jan 2020 16:07:46 +0200 Subject: [PATCH 255/666] Fix test with willReturnMap --- .../Unit/Controller/Store/RedirectTest.php | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) mode change 100644 => 100755 app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php diff --git a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php old mode 100644 new mode 100755 index 1136194fc322a..ff550b912a86f --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -146,20 +146,14 @@ protected function setUp() public function testRedirect(string $defaultStoreViewCode, string $storeCode): void { $this->requestMock - ->expects($this->at(0)) - ->method('getParam') - ->with(StoreResolver::PARAM_NAME) - ->willReturn($storeCode); - $this->requestMock - ->expects($this->at(1)) - ->method('getParam') - ->with('___from_store') - ->willReturn($defaultStoreViewCode); - $this->requestMock - ->expects($this->at(2)) - ->method('getParam') - ->with(ActionInterface::PARAM_NAME_URL_ENCODED) - ->willReturn($defaultStoreViewCode); + ->expects($this->any()) + ->method('getParam')->willReturnMap( + [ + [StoreResolver::PARAM_NAME, null, $storeCode], + ['___from_store', null, $defaultStoreViewCode], + [ActionInterface::PARAM_NAME_URL_ENCODED, null, $defaultStoreViewCode] + ] + ); $this->storeRepositoryMock ->expects($this->once()) ->method('get') From 3e2d9fcc4e7bd7331e6ad1f5b0c56807886a923f Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Thu, 23 Jan 2020 15:18:26 +0100 Subject: [PATCH 256/666] Add frontend template hints status command after suggestions --- .../Command/TemplateHintsStatusCommand.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 98719784a03c4..5905f951aa2a1 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Developer\Console\Command; @@ -10,6 +11,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\Console\Cli; /** @@ -19,21 +21,31 @@ class TemplateHintsStatusCommand extends Command { const COMMAND_NAME = 'dev:template-hints:status'; + const TEMPLATE_HINTS_STOREFRONT_PATH = 'dev/debug/template_hints_storefront'; /** * @var ScopeConfigInterface */ private $scopeConfig; + /** + * @var ReinitableConfigInterface + */ + private $reinitableConfig; /** * Initialize dependencies. * * @param ScopeConfigInterface $scopeConfig + * @param ReinitableConfigInterface $reinitableConfig */ - public function __construct(ScopeConfigInterface $scopeConfig) + public function __construct( + ScopeConfigInterface $scopeConfig, + ReinitableConfigInterface $reinitableConfig + ) { parent::__construct(); $this->scopeConfig = $scopeConfig; + $this->reinitableConfig = $reinitableConfig; } /** @@ -53,6 +65,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->reinitableConfig->reinit(); $templateHintsStatus = ($this->isTemplateHintsEnabled()) ? 'enabled' @@ -66,8 +79,8 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * @return bool */ - private function isTemplateHintsEnabled() + private function isTemplateHintsEnabled(): bool { - return ($this->scopeConfig->isSetFlag('dev/debug/template_hints_storefront', 'default')); + return $this->scopeConfig->isSetFlag(self::TEMPLATE_HINTS_STOREFRONT_PATH, 'default'); } } From a009b97d2b81f18b011b3d85ad8329c9d9f8d4f4 Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <fred@absoluteweb.com> Date: Thu, 23 Jan 2020 11:04:16 -0500 Subject: [PATCH 257/666] Extend exception message --- app/code/Magento/Analytics/Model/Connector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Analytics/Model/Connector.php b/app/code/Magento/Analytics/Model/Connector.php index 23b0ffa213b6e..c48f7f6b41946 100644 --- a/app/code/Magento/Analytics/Model/Connector.php +++ b/app/code/Magento/Analytics/Model/Connector.php @@ -53,7 +53,7 @@ public function __construct( public function execute($commandName) { if (!array_key_exists($commandName, $this->commands)) { - throw new NotFoundException(__('Command was not found.')); + throw new NotFoundException(__('Command "%1" was not found.', $commandName)); } /** @var \Magento\Analytics\Model\Connector\CommandInterface $command */ From 6574e7dac97442ef0ad0b1fc0364e70141cb1a3b Mon Sep 17 00:00:00 2001 From: Dave Macaulay <macaulay@adobe.com> Date: Thu, 23 Jan 2020 10:08:29 -0600 Subject: [PATCH 258/666] MC-30727: Modal slide out will have title set incorrectly when dynamically set --- app/code/Magento/Ui/view/base/web/js/modal/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal.js b/app/code/Magento/Ui/view/base/web/js/modal/modal.js index bcbb2f3c31dbd..f5c284165d8d2 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modal.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js @@ -192,7 +192,7 @@ define([ * @param {String} title */ setTitle: function (title) { - var $title = $(this.options.modalTitle), + var $title = this.modal.find(this.options.modalTitle), $subTitle = this.modal.find(this.options.modalSubTitle); $title.text(title); From ad4ba2e047a7262546fb60a93eb012ac4757559a Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <fred@absoluteweb.com> Date: Thu, 23 Jan 2020 11:09:18 -0500 Subject: [PATCH 259/666] Extend exception message --- .../Magento/Multishipping/Model/Checkout/Type/Multishipping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php index 7fa674505461e..49212202b5f62 100644 --- a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php +++ b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php @@ -1262,7 +1262,7 @@ private function searchQuoteAddressId(OrderInterface $order, array $addresses): } } - throw new NotFoundException(__('Quote address for failed order not found.')); + throw new NotFoundException(__('Quote address for failed order ID "%1" not found.', $order->getEntityId())); } /** From ddc02f814f05dc56b657f07c39680f5f6aec975d Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <fred@absoluteweb.com> Date: Thu, 23 Jan 2020 11:23:20 -0500 Subject: [PATCH 260/666] Update PHP Docs --- .../Magento/Store/Model/Config/Importer/Processor/Create.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index 1fb9f1c224d3e..317e4bf43e42c 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -160,6 +160,7 @@ private function createWebsites(array $items, array $data) * @param array $items Groups to create * @param array $data The all available data * @return void + * @throws NotFoundException */ private function createGroups(array $items, array $data) { @@ -199,6 +200,7 @@ private function createGroups(array $items, array $data) * @param array $items Stores to create * @param array $data The all available data * @return void + * @throws NotFoundException */ private function createStores(array $items, array $data) { From 8357cf80e7cde248c091bf7fef6934c40e47400a Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Fri, 24 Jan 2020 01:11:38 +0530 Subject: [PATCH 261/666] Jasmine test added for initConfig, getByIds, getRequestData, cacheRequest --- .../Ui/base/js/grid/data-storage.test.js | 125 +++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) 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..454fc1280c548 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 @@ -12,7 +12,8 @@ define([ 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { - describe('costructor', function () { + + describe('constructor', function () { it('converts dataScope property to array', function () { var model = new DataStorage({ dataScope: 'magento' @@ -22,6 +23,77 @@ define([ }); }); + describe('"initConfig" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('initConfig')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.initConfig; + + expect(type).toEqual('function'); + }); + + it('Check returned value if method called without arguments', function () { + expect(model.initConfig()).toBeDefined(); + }); + + it('Check returned value type if method called without arguments', function () { + var type = typeof model.initConfig(); + + expect(type).toEqual('object'); + }); + + it('Check this.dataScope property (is modify in initConfig method)', function () { + model.dataScope = null; + model.initConfig(); + expect(typeof model.dataScope).toEqual('object'); + }); + + it('Check this._requests property (is modify in initConfig method)', function () { + model._requests = null; + model.initConfig(); + expect(typeof model._requests).toEqual('object'); + }); + }); + + describe('"getByIds"', function() { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function() { + expect(model.hasOwnProperty('getByIds')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getByIds).toEqual('function'); + }); + + it('Check returned value if method called with argument', function () { + var ids = [1,2,3]; + expect(model.getByIds(ids)).toBeDefined(); + }); + + it('check returned false if method called with argument', function() { + var ids = [1,2,3]; + var type = typeof model.getByIds(ids); + expect(type).toEqual('boolean'); + }); + + it('Return false', function() { + var ids = [1,2,3]; + expect(model.getByIds(ids)).toEqual('false'); + }); + + }); + describe('hasScopeChanged', function () { it('is function', function () { var model = new DataStorage({ @@ -72,5 +144,56 @@ define([ expect(model.hasScopeChanged(newParams)).toBeTruthy(); }); }); + describe('"getRequestData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + it('Check for defined ', function () { + expect(model.hasOwnProperty('getRequestData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.getRequestData; + + expect(type).toEqual('function'); + }); + + it('check "getRequestData" has been executed', function () { + var request = { + ids: [1,2,3] + }; + expect(model.getRequestData(request)).toBeTruthy(); + }); + }); + + describe('"cacheRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + it('Check for defined ', function () { + expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.cacheRequest; + + expect(type).toEqual('function'); + }); + + it('check "cacheRequest" has been executed', function () { + var data = { + items: [1,2,3], + totalRecords: 3, + errorMessage: '' + }, + params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + expect(model.cacheRequest(data, params)).toBeTruthy(); + }); + }); }); }); From c08ccac74c67a44c9d47811a49fb48a37e8a76fc Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko <omiroshnichenko@magento.com> Date: Thu, 23 Jan 2020 14:11:54 -0600 Subject: [PATCH 262/666] MC-30737: Stock sorting doesn't work with table prefix --- app/code/Magento/CatalogInventory/Model/Source/Stock.php | 2 +- .../CatalogInventory/Test/Unit/Model/Source/StockTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogInventory/Model/Source/Stock.php b/app/code/Magento/CatalogInventory/Model/Source/Stock.php index 7d44ab782de61..9661fc83ce275 100644 --- a/app/code/Magento/CatalogInventory/Model/Source/Stock.php +++ b/app/code/Magento/CatalogInventory/Model/Source/Stock.php @@ -42,7 +42,7 @@ public function getAllOptions() public function addValueSortToCollection($collection, $dir = \Magento\Framework\Data\Collection::SORT_ORDER_DESC) { $collection->getSelect()->joinLeft( - ['stock_item_table' => 'cataloginventory_stock_item'], + ['stock_item_table' => $collection->getTable('cataloginventory_stock_item')], "e.entity_id=stock_item_table.product_id", [] ); diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Source/StockTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Source/StockTest.php index 11f41fcaf6d01..1c81e17358e71 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Source/StockTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Source/StockTest.php @@ -25,6 +25,7 @@ public function testAddValueSortToCollection() $selectMock = $this->createMock(\Magento\Framework\DB\Select::class); $collectionMock = $this->createMock(\Magento\Eav\Model\Entity\Collection\AbstractCollection::class); $collectionMock->expects($this->atLeastOnce())->method('getSelect')->willReturn($selectMock); + $collectionMock->expects($this->atLeastOnce())->method('getTable')->willReturn('cataloginventory_stock_item'); $selectMock->expects($this->once()) ->method('joinLeft') From 69e05c0193464f26b4e6a4deb285b8c77456b6f4 Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <fred@absoluteweb.com> Date: Thu, 23 Jan 2020 16:23:14 -0500 Subject: [PATCH 263/666] Update translation file --- app/code/Magento/Analytics/i18n/en_US.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Analytics/i18n/en_US.csv b/app/code/Magento/Analytics/i18n/en_US.csv index 4faa48fb73709..9e86e8ce072c5 100644 --- a/app/code/Magento/Analytics/i18n/en_US.csv +++ b/app/code/Magento/Analytics/i18n/en_US.csv @@ -7,7 +7,7 @@ "There was an error save new configuration value.","There was an error save new configuration value." "Please select an industry.","Please select an industry." "--Please Select--","--Please Select--" -"Command was not found.","Command was not found." +"Command "%1" was not found.","Command "%1" was not found." "Input data must be string or convertible into string.","Input data must be string or convertible into string." "Input data must be non-empty string.","Input data must be non-empty string." "Not valid cipher method.","Not valid cipher method." From 085e52e00733da7e95bb4420ab5661a264a1737b Mon Sep 17 00:00:00 2001 From: Fred Orosko Dias <fred@absoluteweb.com> Date: Thu, 23 Jan 2020 21:51:32 -0500 Subject: [PATCH 264/666] Add translation message --- app/code/Magento/Multishipping/i18n/en_US.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Multishipping/i18n/en_US.csv b/app/code/Magento/Multishipping/i18n/en_US.csv index 43615e697b931..f9ab587c65fa3 100644 --- a/app/code/Magento/Multishipping/i18n/en_US.csv +++ b/app/code/Magento/Multishipping/i18n/en_US.csv @@ -91,3 +91,4 @@ Options,Options "Ship to:","Ship to:" "Error:","Error:" "We are unable to process your request. Please, try again later.","We are unable to process your request. Please, try again later." +"Quote address for failed order ID "%1" not found.","Quote address for failed order ID "%1" not found." From a409774cb18ad48cb0dccf038766e4f8e6cb01ff Mon Sep 17 00:00:00 2001 From: jimuld <37830897+jimuld@users.noreply.github.com> Date: Fri, 24 Jan 2020 10:33:28 +0530 Subject: [PATCH 265/666] Update lib/internal/Magento/Framework/HTTP/Adapter/Curl.php Co-Authored-By: Patrick McLain <pat@pmclain.com> --- lib/internal/Magento/Framework/HTTP/Adapter/Curl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php index df82be8a70e71..067c22564bc45 100644 --- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php @@ -177,7 +177,7 @@ public function write($method, $url, $http_ver = '1.1', $headers = [], $body = ' curl_setopt($this->_getResource(), CURLOPT_HTTPGET, true); curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'GET'); } elseif ($method == \Zend_Http_Client::DELETE) { - curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'DELETE'); curl_setopt($this->_getResource(), CURLOPT_POSTFIELDS, $body); } From 585a7d51dfd2bcef817b0b836fbf579805595df0 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 24 Jan 2020 09:38:35 +0200 Subject: [PATCH 266/666] MC-25108: MFTF Flakiness because of bad design - StoreFrontMyAccountWithMultishipmentTest --- .../StorefrontOrderWithMultishippingTest.xml | 4 ++-- .../AdminOrderCheckStatusActionGroup.xml | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml index dbc1ba980e9c7..ef63d55ccfe35 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StorefrontOrderWithMultishippingTest.xml @@ -93,14 +93,14 @@ <argument name="orderId" value="{$getFirstOrderIdPlaceOrder}"/> </actionGroup> <!-- Check status --> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeFirstOrderPendingStatus"/> + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="seeFirstOrderPendingStatus"/> <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForFirstOrder"/> <!-- Go to order page --> <actionGroup ref="OpenOrderByIdActionGroup" stepKey="openSecondOrderPage"> <argument name="orderId" value="{$getSecondOrderIdPlaceOrder}"/> </actionGroup> <!-- Check status --> - <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Pending" stepKey="seeSecondOrderPendingStatus"/> + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="seeSecondOrderPendingStatus"/> <actionGroup ref="AdminSalesOrderActionGroup" stepKey="validateOrderTotalsForSecondOrder"/> </test> </tests> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.xml new file mode 100644 index 0000000000000..f5d46d165efe5 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderCheckStatusActionGroup.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="AdminOrderViewCheckStatusActionGroup"> + <annotations> + <description>Check order status on order view page.</description> + </annotations> + <arguments> + <argument name="status" type="string" defaultValue="Pending"/> + </arguments> + + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="{{status}}" stepKey="seeOrderStatus"/> + </actionGroup> +</actionGroups> From 24a34475da27a2d821ec873cbe554480c45f4449 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <51681547+engcom-Golf@users.noreply.github.com> Date: Fri, 24 Jan 2020 10:59:31 +0200 Subject: [PATCH 267/666] Update Upsell.php --- app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php index 3c3a78201dddc..37bc356e32db5 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php @@ -232,7 +232,7 @@ public function getIterableItem() * * @param string $type * @param int $limit - * @return Upsell + * @return $this */ public function setItemLimit($type, $limit) { From edf2d040a11e4ccc87e8000c14a25bc5bb572572 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 24 Jan 2020 13:34:38 +0200 Subject: [PATCH 268/666] Covering the fix by MFTF --- ...vigateToCurrencySymbolsPageActionGroup.xml | 15 +++++++ ...minCurrencySymbolIsDisabledActionGroup.xml | 19 +++++++++ .../Mftf/Page/AdminCurrencySymbolsPage.xml | 14 +++++++ .../AdminCurrencySymbolsGridSection.xml | 14 +++++++ ...nDefaultCurrencySymbolsAreDisabledTest.xml | 39 +++++++++++++++++++ 5 files changed, 101 insertions(+) create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminNavigateToCurrencySymbolsPageActionGroup.xml create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AssertAdminCurrencySymbolIsDisabledActionGroup.xml create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/Page/AdminCurrencySymbolsPage.xml create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/Section/AdminCurrencySymbolsGridSection.xml create mode 100644 app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminNavigateToCurrencySymbolsPageActionGroup.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminNavigateToCurrencySymbolsPageActionGroup.xml new file mode 100644 index 0000000000000..58854d2ce8162 --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AdminNavigateToCurrencySymbolsPageActionGroup.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="AdminNavigateToCurrencySymbolsPageActionGroup"> + <amOnPage url="{{AdminCurrencySymbolsPage.url}}" stepKey="navigateToCurrencySymbolsPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AssertAdminCurrencySymbolIsDisabledActionGroup.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AssertAdminCurrencySymbolIsDisabledActionGroup.xml new file mode 100644 index 0000000000000..b8bcb2b0b9cb7 --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/ActionGroup/AssertAdminCurrencySymbolIsDisabledActionGroup.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="AssertAdminCurrencySymbolIsDisabledActionGroup"> + <arguments> + <argument name="currency" type="string"/> + </arguments> + + <grabAttributeFrom selector="{{AdminCurrencySymbolsGridSection.currencyElement(currency)}}" userInput="disabled" stepKey="grabDisabledAttribute"/> + <assertEquals expected='true' expectedType="string" actual="$grabDisabledAttribute" stepKey="assertInputIsDisabled"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Page/AdminCurrencySymbolsPage.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Page/AdminCurrencySymbolsPage.xml new file mode 100644 index 0000000000000..82c2fa70e301a --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Page/AdminCurrencySymbolsPage.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="AdminCurrencySymbolsPage" url="admin/system_currencysymbol/" area="admin" module="CurrencySymbol"> + <section name="AdminCurrencySymbolsGridSection"/> + </page> +</pages> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Section/AdminCurrencySymbolsGridSection.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Section/AdminCurrencySymbolsGridSection.xml new file mode 100644 index 0000000000000..bf087d2ed8f4d --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Section/AdminCurrencySymbolsGridSection.xml @@ -0,0 +1,14 @@ +<?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="AdminCurrencySymbolsGridSection"> + <element name="currencyElement" type="input" selector="#currency-symbols-form #custom_currency_symbol{{currency}}" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.xml new file mode 100644 index 0000000000000..a04128c3d5ded --- /dev/null +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Test/AdminDefaultCurrencySymbolsAreDisabledTest.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="AdminCurrencySymbolsAreDisabledTest"> + <annotations> + <features value="CurrencySymbol"/> + <stories value="Currency Symbols"/> + <title value="Currency symbols are disabled by default"/> + <description value="Currency symbols should be disabled by default"/> + <severity value="MINOR"/> + <group value="currency"/> + </annotations> + <before> + <magentoCLI command="config:set --scope={{SetAllowedCurrenciesConfigForUSD.scope}} --scope-code={{SetAllowedCurrenciesConfigForUSD.scope_code}} {{SetAllowedCurrenciesConfigForUSD.path}} {{SetAllowedCurrenciesConfigForUSD.value}},{{SetAllowedCurrenciesConfigForEUR.value}},{{SetAllowedCurrenciesConfigForRUB.value}}" stepKey="setAllowedCurrencyWebsites_EUR_RUB_USD"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </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"/> + </after> + <actionGroup ref="AdminNavigateToCurrencySymbolsPageActionGroup" stepKey="navigateToCurrencySymbolsPage"/> + <actionGroup ref="AssertAdminCurrencySymbolIsDisabledActionGroup" stepKey="assertEURDisabledInput"> + <argument name="currency" value="{{SetAllowedCurrenciesConfigForEUR.value}}"/> + </actionGroup> + <actionGroup ref="AssertAdminCurrencySymbolIsDisabledActionGroup" stepKey="assertUSDDisabledInput"> + <argument name="currency" value="{{SetAllowedCurrenciesConfigForUSD.value}}"/> + </actionGroup> + <actionGroup ref="AssertAdminCurrencySymbolIsDisabledActionGroup" stepKey="assertRUBDisabledInput"> + <argument name="currency" value="{{SetAllowedCurrenciesConfigForRUB.value}}"/> + </actionGroup> + </test> +</tests> From ed4c01bd01b7a70d44a1f9ee2c534bdd896f2da5 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 24 Jan 2020 13:51:07 +0200 Subject: [PATCH 269/666] Ignoring unescaped output warning --- .../Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 9298f0d3ce1d8..353137a4dcb2e 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -31,7 +31,9 @@ ?> <input id="custom_currency_symbol_inherit<?= $block->escapeHtmlAttr($code) ?>" class="admin__control-checkbox" type="checkbox" + <?php //@codingStandardsIgnoreStart ?> onclick="toggleUseDefault(<?= '\'' . $escapedCode . '\',\'' . $escapedSymbol . '\'' ?>)" + <?php //@codingStandardsIgnoreEnd ?> <?= $data['inherited'] ? ' checked="checked"' : '' ?> value="1" name="inherit_custom_currency_symbol[<?= $block->escapeHtmlAttr($code) ?>]"> From 79b0aa77223c5f61d3af9f7a44c5d078b8db91af Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Fri, 24 Jan 2020 14:44:43 +0200 Subject: [PATCH 270/666] MC-23753: "<" and ">" symbols are changed to "<" and ">" in the frontend catalog search line --- .../Magento/Search/view/frontend/templates/form.mini.phtml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index 0dd9c819c855a..35f3876599731 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -14,7 +14,8 @@ $helper = $this->helper(\Magento\Search\Helper\Data::class); <div class="block block-search"> <div class="block block-title"><strong><?= $block->escapeHtml(__('Search')) ?></strong></div> <div class="block block-content"> - <form class="form minisearch" id="search_mini_form" action="<?= $block->escapeUrl($helper->getResultUrl()) ?>" method="get"> + <form class="form minisearch" id="search_mini_form" + action="<?= $block->escapeUrl($helper->getResultUrl()) ?>" method="get"> <div class="field search"> <label class="label" for="search" data-role="minisearch-label"> <span><?= $block->escapeHtml(__('Search')) ?></span> @@ -29,7 +30,7 @@ $helper = $this->helper(\Magento\Search\Helper\Data::class); }' type="text" name="<?= $block->escapeHtmlAttr($helper->getQueryParamName()) ?>" - value="<?= $block->escapeHtmlAttr($helper->getEscapedQueryText()) ?>" + value="<?= /* @noEscape */ $helper->getEscapedQueryText() ?>" placeholder="<?= $block->escapeHtmlAttr(__('Search entire store here...')) ?>" class="input-text" maxlength="<?= $block->escapeHtmlAttr($helper->getMaxQueryLength()) ?>" From 78329252e8f4adedae98a99c1fbc44529536cd92 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Fri, 24 Jan 2020 14:51:09 +0200 Subject: [PATCH 271/666] Http adapter curl missing delete method Fix static tests & use strict comparison --- lib/internal/Magento/Framework/HTTP/Adapter/Curl.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php index 067c22564bc45..19b23abbc44d4 100644 --- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php @@ -166,22 +166,21 @@ public function write($method, $url, $http_ver = '1.1', $headers = [], $body = ' // set url to post to curl_setopt($this->_getResource(), CURLOPT_URL, $url); curl_setopt($this->_getResource(), CURLOPT_RETURNTRANSFER, true); - if ($method == \Zend_Http_Client::POST) { + if ($method === \Zend_Http_Client::POST) { curl_setopt($this->_getResource(), CURLOPT_POST, true); curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($this->_getResource(), CURLOPT_POSTFIELDS, $body); - } elseif ($method == \Zend_Http_Client::PUT) { + } elseif ($method === \Zend_Http_Client::PUT) { curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($this->_getResource(), CURLOPT_POSTFIELDS, $body); - } elseif ($method == \Zend_Http_Client::GET) { + } elseif ($method === \Zend_Http_Client::GET) { curl_setopt($this->_getResource(), CURLOPT_HTTPGET, true); curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'GET'); - } elseif ($method == \Zend_Http_Client::DELETE) { + } elseif ($method === \Zend_Http_Client::DELETE) { curl_setopt($this->_getResource(), CURLOPT_CUSTOMREQUEST, 'DELETE'); curl_setopt($this->_getResource(), CURLOPT_POSTFIELDS, $body); } - if ($http_ver === \Zend_Http_Client::HTTP_1) { curl_setopt($this->_getResource(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); } elseif ($http_ver === \Zend_Http_Client::HTTP_0) { From b43980b94cdd208ee80e0e2cc9fc302469d96439 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Fri, 24 Jan 2020 14:57:51 +0200 Subject: [PATCH 272/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Fixed grids export: option labels are taken from grid filters and columns now. --- .../Ui/Model/Export/MetadataProvider.php | 86 +++++++++++++++---- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index 3f6685e37fcc4..1ce3562c06cc3 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -3,19 +3,27 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + 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 @@ -76,7 +84,7 @@ public function __construct( * * @param UiComponentInterface $component * @return UiComponentInterface - * @throws \Exception + * @throws Exception */ protected function getColumnsComponent(UiComponentInterface $component) { @@ -85,14 +93,16 @@ protected function getColumnsComponent(UiComponentInterface $component) 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) { @@ -111,7 +121,9 @@ protected function getColumns(UiComponentInterface $component) * Retrieve Headers row array for Export * * @param UiComponentInterface $component + * * @return string[] + * @throws Exception */ public function getHeaders(UiComponentInterface $component) { @@ -127,7 +139,9 @@ public function getHeaders(UiComponentInterface $component) * Returns DB fields list * * @param UiComponentInterface $component + * * @return array + * @throws Exception */ public function getFields(UiComponentInterface $component) { @@ -184,34 +198,73 @@ 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() + { + return array_merge( + $this->getColumnOptions(), + $this->getFilterOptions() + ); + } + + /** + * Get options from columns. + * + * @return array + * @throws LocalizedException + * @throws Exception + */ + protected function getColumnOptions() + { + $options = []; + $component = $this->filter->getComponent(); + /** @var Column $columnComponent */ + foreach ($this->getColumns($component) as $columnComponent) { + /** @var OptionSourceInterface $options */ + if ($optionSource = $columnComponent->getData('options')) { + $options[$columnComponent->getName()] = $this->getOptionsArray($optionSource->toOptionArray()); + } + } + + return $options; + } + + /** + * Get options from column filters. + * + * @return array + * @throws LocalizedException + */ + protected function getFilterOptions() { $options = []; $component = $this->filter->getComponent(); @@ -221,7 +274,7 @@ 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')); } } } @@ -232,9 +285,10 @@ public function getOptions() /** * 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) { @@ -247,7 +301,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 ); From 93793d8af1c0de796df340beb9f8707a941e28f1 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Fri, 24 Jan 2020 15:26:57 +0200 Subject: [PATCH 273/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Implemented strict types. --- .../Ui/Model/Export/MetadataProvider.php | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index 1ce3562c06cc3..56529166dc0b6 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Ui\Model\Export; @@ -83,10 +84,11 @@ public function __construct( * Returns Columns component * * @param UiComponentInterface $component + * * @return UiComponentInterface * @throws Exception */ - protected function getColumnsComponent(UiComponentInterface $component) + protected function getColumnsComponent(UiComponentInterface $component): UiComponentInterface { foreach ($component->getChildComponents() as $childComponent) { if ($childComponent instanceof Columns) { @@ -104,7 +106,7 @@ protected function getColumnsComponent(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); @@ -114,6 +116,7 @@ protected function getColumns(UiComponentInterface $component) } } } + return $this->columns[$component->getName()]; } @@ -125,7 +128,7 @@ protected function getColumns(UiComponentInterface $component) * @return string[] * @throws Exception */ - public function getHeaders(UiComponentInterface $component) + public function getHeaders(UiComponentInterface $component): array { $row = []; foreach ($this->getColumns($component) as $column) { @@ -140,15 +143,16 @@ public function getHeaders(UiComponentInterface $component) * * @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; } @@ -158,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) { @@ -175,6 +180,7 @@ public function getRowData(DocumentInterface $document, $fields, $options) $row[] = $document->getCustomAttribute($column)->getValue(); } } + return $row; } @@ -184,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'])) { @@ -228,7 +235,7 @@ protected function getOptionsArray(array $options): array * @return array * @throws LocalizedException */ - public function getOptions() + public function getOptions(): array { return array_merge( $this->getColumnOptions(), @@ -243,7 +250,7 @@ public function getOptions() * @throws LocalizedException * @throws Exception */ - protected function getColumnOptions() + protected function getColumnOptions(): array { $options = []; $component = $this->filter->getComponent(); @@ -264,7 +271,7 @@ protected function getColumnOptions() * @return array * @throws LocalizedException */ - protected function getFilterOptions() + protected function getFilterOptions(): array { $options = []; $component = $this->filter->getComponent(); @@ -279,6 +286,7 @@ protected function getFilterOptions() } } } + return $options; } @@ -287,10 +295,11 @@ protected function getFilterOptions() * * @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; From c517f5f75c64c89dd46d639980f94cfc3e3f158b Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Fri, 24 Jan 2020 16:12:26 +0200 Subject: [PATCH 274/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Fixed case when options are configured via XML directly instead of providing a class. --- app/code/Magento/Ui/Model/Export/MetadataProvider.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index 56529166dc0b6..b47b4c0f57d14 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -256,9 +256,11 @@ protected function getColumnOptions(): array $component = $this->filter->getComponent(); /** @var Column $columnComponent */ foreach ($this->getColumns($component) as $columnComponent) { - /** @var OptionSourceInterface $options */ - if ($optionSource = $columnComponent->getData('options')) { - $options[$columnComponent->getName()] = $this->getOptionsArray($optionSource->toOptionArray()); + if ($columnComponent->hasData('options')) { + $optionSource = $columnComponent->getData('options'); + $optionsArray = $optionSource instanceof OptionSourceInterface ? + $optionSource->toOptionArray() : $optionSource; + $options[$columnComponent->getName()] = $this->getOptionsArray($optionsArray); } } From 0671b7f013d11f06bef65cdb8a0c5342834e89fd Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 24 Jan 2020 16:14:02 +0200 Subject: [PATCH 275/666] Added strict_types --- .../Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php index a1c461a10abdc..a5cd261ab7121 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Fedex\Test\Unit\Plugin\Block\Tracking; use Magento\Fedex\Model\Carrier; From e69ff7b0fe2ac2757bc28ab4c5293288675f44d4 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 24 Jan 2020 16:24:33 +0200 Subject: [PATCH 276/666] Added strict_types and some cleanup --- .../Block/DataProviders/Tracking/ChangeTitleTest.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php index dc3218411b748..ff1276044d731 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/DataProviders/Tracking/ChangeTitleTest.php @@ -4,8 +4,11 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Fedex\Test\Unit\Plugin\Block\DataProviders\Tracking; +use Magento\Fedex\Model\Carrier; use Magento\Fedex\Plugin\Block\DataProviders\Tracking\ChangeTitle; use Magento\Framework\Phrase; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -15,7 +18,7 @@ use PHPUnit\Framework\TestCase; /** - * Unit Test for @see \Magento\Fedex\Plugin\Block\DataProviders\Tracking\ChangeTitle + * Unit Test for @see ChangeTitle */ class ChangeTitleTest extends TestCase { @@ -41,7 +44,7 @@ protected function setUp() * @param Phrase|string $finalResult * @dataProvider testAfterGetTitleDataProvider */ - public function testAfterGetTitle($carrierCode, $originalResult, $finalResult) + public function testAfterGetTitle(string $carrierCode, string $originalResult, $finalResult) { /** @var DeliveryDateTitle|MockObject $subjectMock */ $subjectMock = $this->getMockBuilder(DeliveryDateTitle::class) @@ -67,10 +70,10 @@ public function testAfterGetTitle($carrierCode, $originalResult, $finalResult) * * @return array */ - public function testAfterGetTitleDataProvider() + public function testAfterGetTitleDataProvider(): array { return [ - [\Magento\Fedex\Model\Carrier::CODE, 'Original Title', __('Expected Delivery:')], + [Carrier::CODE, 'Original Title', __('Expected Delivery:')], ['not-fedex', 'Original Title', 'Original Title'], ]; } From 52a66acc44a3f7dff0e3eaf1166cec6d279d29be Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 24 Jan 2020 16:30:17 +0200 Subject: [PATCH 277/666] Unit test for Magento\Reports\Observer\EventSaver --- .../Test/Unit/Observer/EventSaverTest.php | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php diff --git a/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php new file mode 100644 index 0000000000000..8175887a33903 --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php @@ -0,0 +1,156 @@ +<?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\Customer\Model\Session; +use Magento\Customer\Model\Visitor; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Reports\Model\Event; +use Magento\Reports\Model\EventFactory; +use Magento\Reports\Observer\EventSaver; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for @see EventSaver + */ +class EventSaverTest extends TestCase +{ + /** + * @var Session|MockObject + */ + private $customerSessionMock; + + /** + * @var Visitor|MockObject + */ + private $customerVisitorMock; + + /** + * @var StoreInterface|MockObject + */ + private $storeMock; + + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManagerMock; + + /** + * @var EventFactory|MockObject + */ + private $eventFactoryMock; + + /** + * @var Event|MockObject + */ + private $eventMock; + + /** + * @var EventSaver + */ + private $eventSaver; + + /** + * @inheritDoc + */ + public function setUp() + { + $this->customerSessionMock = $this->createMock(Session::class); + $this->customerVisitorMock = $this->createMock(Visitor::class); + + $this->storeMock = $this->createMock(StoreInterface::class); + $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); + $this->storeManagerMock->expects($this->once()) + ->method('getStore') + ->willReturn($this->storeMock); + $this->storeMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + + $this->eventMock = $this->createMock(Event::class); + $this->eventFactoryMock = $this->createMock(EventFactory::class); + $this->eventFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->eventMock); + $this->eventMock->expects($this->once()) + ->method('setData') + ->willReturnSelf(); + $this->eventMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $objectManagerHelper = new ObjectManager($this); + $this->eventSaver = $objectManagerHelper->getObject( + EventSaver::class, + [ + '_storeManager' => $this->storeManagerMock, + '_eventFactory' => $this->eventFactoryMock, + '_customerSession' => $this->customerSessionMock, + '_customerVisitor' => $this->customerVisitorMock + ] + ); + } + + /** + * Test save with subject ID provided + */ + public function testSaveWithSubject() + { + $subjectId = 5; + $this->customerSessionMock->expects($this->never()) + ->method('isLoggedIn'); + $this->customerSessionMock->expects($this->never()) + ->method('getCustomerId'); + $this->customerVisitorMock->expects($this->never()) + ->method('getId'); + $this->eventSaver->save(1, 1, $subjectId); + } + + /** + * Test save with no subject ID provided + * + * @param bool $isLoggedIn + * @dataProvider dataProviderTestSaveWithoutSubject + */ + public function testSaveWithoutSubject(bool $isLoggedIn) + { + if ($isLoggedIn) { + $this->customerSessionMock->expects($this->once()) + ->method('isLoggedIn') + ->willReturn(true); + $this->customerSessionMock->expects($this->once()) + ->method('getCustomerId') + ->willReturn(1); + } else { + $this->customerSessionMock->expects($this->once()) + ->method('isLoggedIn') + ->willReturn(false); + $this->customerVisitorMock->expects($this->once()) + ->method('getId') + ->willReturn(2); + } + $this->eventSaver->save(1, 1, null); + } + + /** + * Data provider for a case without subjectId provided + * + * @return array + */ + public function dataProviderTestSaveWithoutSubject() + { + return [ + [true], + [false] + ]; + } +} From 75c2fb5489b7aaf601925482f270ebf15419a531 Mon Sep 17 00:00:00 2001 From: vadim <vadim@example.com> Date: Fri, 24 Jan 2020 13:31:31 +0200 Subject: [PATCH 278/666] magento/magento2#25966: `Next` button position fix --- .../web/css/source/module/checkout/_shipping.less | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less index 2eb634acc5daa..f054140c0e1b2 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less @@ -211,6 +211,12 @@ } } } + + #shipping-method-buttons-container { + .button { + margin-top: 2px; + } + } } // From 45cd0fa332f5eb32e4e49a2e055ecb57d8442afa Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Fri, 24 Jan 2020 18:40:48 +0200 Subject: [PATCH 279/666] Refactored MFTF test --- ...orefrontCreateNewSubscriberActionGroup.xml | 19 +++++++++++++++++++ ...erConfigPageSubscriptionOptionsSection.xml | 2 +- .../Section/NewsletterTemplateSection.xml | 3 ++- ...inkDisplayedForGuestSubscriptionNoTest.xml | 6 +----- 4 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Newsletter/Test/Mftf/ActionGroup/StorefrontCreateNewSubscriberActionGroup.xml diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/StorefrontCreateNewSubscriberActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/StorefrontCreateNewSubscriberActionGroup.xml new file mode 100644 index 0000000000000..0aee2cb9b2e3c --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/StorefrontCreateNewSubscriberActionGroup.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="StorefrontCreateNewSubscriberActionGroup"> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <submitForm selector="{{BasicFrontendNewsletterFormSection.subscribeForm}}" + parameterArray="['email' => '{{_defaultNewsletter.senderEmail}}']" + button="{{BasicFrontendNewsletterFormSection.subscribeButton}}" stepKey="submitForm"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForElementVisible stepKey="waitForErrorAppears" selector="{{StorefrontMessagesSection.error}}"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml index 26fdcf10ede02..32bedfead088c 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/AdminNewsletterConfigPageSubscriptionOptionsSection.xml @@ -8,7 +8,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminNewsletterConfigPageSubscriptionOptionsSection"> - <element name="allowGuestSubscription" type="input" selector="#newsletter_subscription_allow_guest_subscribe_inherit"/> + <element name="allowGuestSubscription" type="checkbox" selector="input[name='groups[subscription][fields][allow_guest_subscribe][inherit]']" timeout="30"/> <element name="guestSubscription" type="select" selector="#newsletter_subscription_allow_guest_subscribe" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml index ebc1577fd5ece..ffc871c56800b 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Section/NewsletterTemplateSection.xml @@ -9,7 +9,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="BasicFrontendNewsletterFormSection"> <element name="newsletterEmail" type="input" selector="#newsletter"/> - <element name="subscribeButton" type="button" selector=".subscribe"/> + <element name="subscribeButton" type="button" selector=".subscribe" timeout="30"/> + <element name="subscribeForm" type="input" selector="#newsletter-validate-detail" timeout="30"/> </section> <section name="BasicFieldNewsletterSection"> <element name="templateName" type="input" selector="#code"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml index b5cb4e2fa62bc..f4dc370391b64 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml @@ -17,10 +17,6 @@ <!--Log out from Magento admin.--> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </before> - - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <fillField selector="{{BasicFrontendNewsletterFormSection.newsletterEmail}}" userInput="{{_defaultNewsletter.senderEmail}}" stepKey="fillTemplateEmail" /> - <click selector="{{BasicFrontendNewsletterFormSection.subscribeButton}}" stepKey="subscribe"/> - <waitForElement selector=".messages" stepKey="waitMessage"/> + <actionGroup ref="StorefrontCreateNewSubscriberActionGroup" stepKey="createSubscriber"/> </test> </tests> From fd3f2a22b8e5b2cffaf17daccc29f461c26c5f51 Mon Sep 17 00:00:00 2001 From: Yevhen Sentiabov <sentiabo@adobe.com> Date: Fri, 24 Jan 2020 14:26:19 -0600 Subject: [PATCH 280/666] Github #26532: di:setup:compile fails with anonymous classes - Fixed parsing for anonymous classes during di:compile run - Small code optimizations - Extended and refactored related unit tests --- .../Module/Di/Code/Scanner/PhpScanner.php | 86 ++++++++++--------- .../Di/Code/Reader/ClassesScannerTest.php | 4 +- .../Module/Di/Code/Scanner/PhpScannerTest.php | 84 +++++++++--------- .../Model/StubWithAnonymousClass.php | 36 ++++++++ 4 files changed, 128 insertions(+), 82 deletions(-) create mode 100644 setup/src/Magento/Setup/Test/Unit/Module/Di/_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php diff --git a/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php index 1cd242acbe50b..be25cf605ef80 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Setup\Module\Di\Code\Scanner; use Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator; @@ -12,9 +14,7 @@ use \Magento\Framework\Reflection\TypeProcessor; /** - * Class PhpScanner - * - * @package Magento\Setup\Module\Di\Code\Scanner + * Finds factory and extension attributes classes which require auto-generation. */ class PhpScanner implements ScannerInterface { @@ -53,15 +53,28 @@ public function __construct(Log $log, TypeProcessor $typeProcessor = null) protected function _findMissingClasses($file, $classReflection, $methodName, $entityType) { $missingClasses = []; - if ($classReflection->hasMethod($methodName)) { - $constructor = $classReflection->getMethod($methodName); - $parameters = $constructor->getParameters(); - /** @var $parameter \ReflectionParameter */ - foreach ($parameters as $parameter) { - preg_match('/\[\s\<\w+?>\s([\w\\\\]+)/s', $parameter->__toString(), $matches); - if (isset($matches[1]) && substr($matches[1], -strlen($entityType)) == $entityType) { - $missingClassName = $matches[1]; - if ($this->shouldGenerateClass($missingClassName, $entityType, $file)) { + if (!$classReflection->hasMethod($methodName)) { + return $missingClasses; + } + + $factorySuffix = '\\' . ucfirst(FactoryGenerator::ENTITY_TYPE); + $constructor = $classReflection->getMethod($methodName); + $parameters = $constructor->getParameters(); + /** @var $parameter \ReflectionParameter */ + foreach ($parameters as $parameter) { + preg_match('/\[\s\<\w+?>\s([\w\\\\]+)/s', $parameter->__toString(), $matches); + if (isset($matches[1]) && substr($matches[1], -strlen($entityType)) == $entityType) { + $missingClassName = $matches[1]; + if ($this->shouldGenerateClass($missingClassName, $entityType, $file)) { + + if (substr($missingClassName, -strlen($factorySuffix)) == $factorySuffix) { + $entityName = rtrim(substr($missingClassName, 0, -strlen($factorySuffix)), '\\'); + $this->_log->add( + Log::CONFIGURATION_ERROR, + $missingClassName, + 'Invalid Factory declaration for class ' . $entityName . ' in file ' . $file + ); + } else { $missingClasses[] = $missingClassName; } } @@ -110,24 +123,12 @@ protected function getSourceClassName($missingClassName, $entityType) */ protected function _fetchFactories($reflectionClass, $file) { - $factorySuffix = '\\' . ucfirst(FactoryGenerator::ENTITY_TYPE); $absentFactories = $this->_findMissingClasses( $file, $reflectionClass, '__construct', ucfirst(FactoryGenerator::ENTITY_TYPE) ); - foreach ($absentFactories as $key => $absentFactory) { - if (substr($absentFactory, -strlen($factorySuffix)) == $factorySuffix) { - $entityName = rtrim(substr($absentFactory, 0, -strlen($factorySuffix)), '\\'); - $this->_log->add( - Log::CONFIGURATION_ERROR, - $absentFactory, - 'Invalid Factory declaration for class ' . $entityName . ' in file ' . $file - ); - unset($absentFactories[$key]); - } - } return $absentFactories; } @@ -150,21 +151,19 @@ protected function _fetchMissingExtensionAttributesClasses($reflectionClass, $fi $missingClassName = $returnType['type']; if ($this->shouldGenerateClass($missingClassName, $entityType, $file)) { $missingExtensionInterfaces[] = $missingClassName; + + $extension = rtrim(substr($missingClassName, 0, -strlen('Interface')), '\\'); + if (!class_exists($extension)) { + $missingExtensionInterfaces[] = $extension; + } + $extensionFactory = $extension . 'Factory'; + if (!class_exists($extensionFactory)) { + $missingExtensionInterfaces[] = $extensionFactory; + } } } - $missingExtensionClasses = []; - $missingExtensionFactories = []; - foreach ($missingExtensionInterfaces as $missingExtensionInterface) { - $extension = rtrim(substr($missingExtensionInterface, 0, -strlen('Interface')), '\\'); - if (!class_exists($extension)) { - $missingExtensionClasses[] = $extension; - } - $extensionFactory = $extension . 'Factory'; - if (!class_exists($extensionFactory)) { - $missingExtensionFactories[] = $extensionFactory; - } - } - return array_merge($missingExtensionInterfaces, $missingExtensionClasses, $missingExtensionFactories); + + return $missingExtensionInterfaces; } /** @@ -223,8 +222,17 @@ protected function _fetchClasses($namespace, $tokenIterator, $count, $tokens) { $classes = []; for ($tokenOffset = $tokenIterator + 1; $tokenOffset < $count; ++$tokenOffset) { - if ($tokens[$tokenOffset] === '{') { - $classes[] = $namespace . "\\" . $tokens[$tokenIterator + 2][1]; + if ($tokens[$tokenOffset] !== '{') { + continue; + } + // anonymous classes should be omitted + if (is_array($tokens[$tokenIterator - 2]) && $tokens[$tokenIterator - 2][0] === T_NEW) { + continue; + } + + $class = $namespace . "\\" . $tokens[$tokenIterator + 2][1]; + if (!in_array($class, $classes)) { + $classes[] = $class; } } return $classes; diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/ClassesScannerTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/ClassesScannerTest.php index efb7e72b0ed08..4d9cd140122ad 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/ClassesScannerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Reader/ClassesScannerTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Setup\Test\Unit\Module\Di\Code\Reader; use Magento\Framework\App\Filesystem\DirectoryList; @@ -37,6 +39,6 @@ public function testGetList() $pathToScan = str_replace('\\', '/', realpath(__DIR__ . '/../../') . '/_files/app/code/Magento/SomeModule'); $actual = $this->model->getList($pathToScan); $this->assertTrue(is_array($actual)); - $this->assertCount(5, $actual); + $this->assertCount(6, $actual); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php index 5f8cd7643e87c..46d45770055b0 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php @@ -3,74 +3,74 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Setup\Test\Unit\Module\Di\Code\Scanner; +declare(strict_types=1); -require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Helper/Test.php'; -require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/ElementFactory.php'; -require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/DoubleColon.php'; -require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Api/Data/SomeInterface.php'; +namespace Magento\Setup\Test\Unit\Module\Di\Code\Scanner; use Magento\Framework\Reflection\TypeProcessor; +use Magento\Setup\Module\Di\Code\Scanner\PhpScanner; +use Magento\Setup\Module\Di\Compiler\Log\Log; +use PHPUnit\Framework\MockObject\MockObject; class PhpScannerTest extends \PHPUnit\Framework\TestCase { /** - * @var \Magento\Setup\Module\Di\Code\Scanner\PhpScanner + * @var PhpScanner */ - protected $_model; + private $scanner; /** * @var string */ - protected $_testDir; - - /** - * @var array - */ - protected $_testFiles = []; + private $testDir; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var Log|MockObject */ - protected $_logMock; + private $log; protected function setUp() { - $this->_logMock = $this->createMock(\Magento\Setup\Module\Di\Compiler\Log\Log::class); - $this->_model = new \Magento\Setup\Module\Di\Code\Scanner\PhpScanner($this->_logMock, new TypeProcessor()); - $this->_testDir = str_replace('\\', '/', realpath(__DIR__ . '/../../') . '/_files'); + $this->log = $this->createMock(Log::class); + $this->scanner = new PhpScanner($this->log, new TypeProcessor()); + $this->testDir = str_replace('\\', '/', realpath(__DIR__ . '/../../') . '/_files'); } public function testCollectEntities() { - $this->_testFiles = [ - $this->_testDir . '/app/code/Magento/SomeModule/Helper/Test.php', - $this->_testDir . '/app/code/Magento/SomeModule/Model/DoubleColon.php', - $this->_testDir . '/app/code/Magento/SomeModule/Api/Data/SomeInterface.php' + require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Helper/Test.php'; + require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/ElementFactory.php'; + require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/DoubleColon.php'; + require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Api/Data/SomeInterface.php'; + require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php'; + + $testFiles = [ + $this->testDir . '/app/code/Magento/SomeModule/Helper/Test.php', + $this->testDir . '/app/code/Magento/SomeModule/Model/DoubleColon.php', + $this->testDir . '/app/code/Magento/SomeModule/Api/Data/SomeInterface.php', + $this->testDir . '/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php', ]; - $this->_logMock->expects( - $this->at(0) - )->method( - 'add' - )->with( - 4, - 'Magento\SomeModule\Module\Factory', - 'Invalid Factory for nonexistent class Magento\SomeModule\Module in file ' . $this->_testFiles[0] - ); - $this->_logMock->expects( - $this->at(1) - )->method( - 'add' - )->with( - 4, - 'Magento\SomeModule\Element\Factory', - 'Invalid Factory declaration for class Magento\SomeModule\Element in file ' . $this->_testFiles[0] - ); + $this->log->expects(self::at(0)) + ->method('add') + ->with( + 4, + 'Magento\SomeModule\Module\Factory', + 'Invalid Factory for nonexistent class Magento\SomeModule\Module in file ' . $testFiles[0] + ); + $this->log->expects(self::at(1)) + ->method('add') + ->with( + 4, + 'Magento\SomeModule\Element\Factory', + 'Invalid Factory declaration for class Magento\SomeModule\Element in file ' . $testFiles[0] + ); + + $result = $this->scanner->collectEntities($testFiles); - $this->assertEquals( + self::assertEquals( ['\\' . \Magento\Eav\Api\Data\AttributeExtensionInterface::class], - $this->_model->collectEntities($this->_testFiles) + $result ); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php new file mode 100644 index 0000000000000..793ee3bb16cdb --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\SomeModule\Model; + +use Magento\SomeModule\DummyFactory; + +class StubWithAnonymousClass +{ + /** + * @var DummyFactory + */ + private $factory; + + public function __construct(DummyFactory $factory) + { + $this->factory = $factory; + } + + public function getSerializable(): \JsonSerializable + { + return new class() implements \JsonSerializable { + /** + * @inheritDoc + */ + public function jsonSerialize() + { + return [1, 2, 3]; + } + }; + } +} From 7fa8e4ca812c0d71bf237ac17c757b928bb4276e Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Fri, 24 Jan 2020 14:58:28 -0600 Subject: [PATCH 281/666] magento/magento2#26391 MFTF: Add missing tests annotations - test fix --- .../Test/Mftf/ActionGroup/DeleteTermActionGroup.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CheckoutAgreements/Test/Mftf/ActionGroup/DeleteTermActionGroup.xml b/app/code/Magento/CheckoutAgreements/Test/Mftf/ActionGroup/DeleteTermActionGroup.xml index b88101ce88ef6..13163e90efdbc 100644 --- a/app/code/Magento/CheckoutAgreements/Test/Mftf/ActionGroup/DeleteTermActionGroup.xml +++ b/app/code/Magento/CheckoutAgreements/Test/Mftf/ActionGroup/DeleteTermActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="DeleteTermActionGroup"> <arguments> - <argument name="term" /> + <argument name="term"/> </arguments> <amOnPage url="{{AdminTermsPage.url}}" stepKey="onTermGridPage"/> <waitForPageLoad stepKey="waitForAdminTermsGridPageLoad"/> @@ -19,8 +19,8 @@ <click selector="{{AdminTermGridSection.firstRowConditionId}}" stepKey="clickFirstRow"/> <waitForPageLoad stepKey="waitForEditTermPageLoad"/> <click selector="{{AdminEditTermFormSection.delete}}" stepKey="clickDeleteButton"/> + <waitForElementVisible selector="{{AdminEditTermFormSection.acceptPopupButton}}" stepKey="waitForElement"/> <click selector="{{AdminEditTermFormSection.acceptPopupButton}}" stepKey="clickDeleteOkButton"/> - <waitForPageLoad stepKey="waitForAdminTermsGridPageLoad2"/> - <see selector="{{AdminTermFormMessagesSection.successMessage}}" userInput="You deleted the condition." stepKey="seeSuccessMessage"/> + <waitForText selector="{{AdminTermFormMessagesSection.successMessage}}" userInput="You deleted the condition." stepKey="seeSuccessMessage"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> From 8c01f7c07550cd8d7bd564ceb1af7680723a4c9e Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Sat, 25 Jan 2020 11:09:47 +0200 Subject: [PATCH 282/666] MC-30528: Inconsisten behavior when importing configurable products with custom options and when specifying store_view_code --- .../Model/Import/Product/Option.php | 25 +++++++---- .../Model/Import/ProductTest.php | 41 +++++++++++++++---- ...ustom_options_and_multiple_store_views.csv | 4 ++ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 4c716421b7ae6..e12fc726f1056 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -6,14 +6,14 @@ namespace Magento\CatalogImportExport\Model\Import\Product; -use Magento\CatalogImportExport\Model\Import\Product; -use Magento\Framework\App\ResourceConnection; -use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection as ProductOptionValueCollection; use Magento\Catalog\Model\ResourceModel\Product\Option\Value\CollectionFactory as ProductOptionValueCollectionFactory; -use Magento\Store\Model\Store; +use Magento\CatalogImportExport\Model\Import\Product; +use Magento\Framework\App\ResourceConnection; use Magento\ImportExport\Model\Import; +use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; +use Magento\Store\Model\Store; /** * Entity class which provide possibility to import product custom options @@ -110,6 +110,13 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity 'file' => ['sku', 'file_extension', 'image_size_x', 'image_size_y'], ]; + /** + * Invalid rows list + * + * @var array + */ + private $_invalidRows; + /** * Keep product id value for every row which will be imported * @@ -433,7 +440,7 @@ protected function _initMessageTemplates() self::ERROR_INVALID_TYPE, __( 'Value for \'type\' sub attribute in \'custom_options\' attribute contains incorrect value, acceptable values are: %1', - '\''.implode('\', \'', array_keys($this->_specificTypes)).'\'' + '\'' . implode('\', \'', array_keys($this->_specificTypes)) . '\'' ) ); $this->_productEntity->addMessageTemplate(self::ERROR_EMPTY_TITLE, __('Please enter a value for title.')); @@ -1251,7 +1258,9 @@ protected function _importData() $childCount = []; $optionsToRemove = []; foreach ($bunch as $rowNumber => $rowData) { - if (isset($optionId, $valueId) && empty($rowData[PRODUCT::COL_STORE_VIEW_CODE])) { + if (isset($optionId, $valueId) && + (empty($rowData[PRODUCT::COL_STORE_VIEW_CODE]) || empty($rowData['custom_options'])) + ) { $nextOptionId = $optionId; $nextValueId = $valueId; } @@ -1548,8 +1557,8 @@ protected function _collectOptionTitle(array $rowData, $prevOptionId, array &$ti if (!empty($rowData[self::COLUMN_TITLE])) { if (!isset($titles[$prevOptionId][$defaultStoreId])) { if (isset($this->lastOptionTitle[$prevOptionId])) { - $titles[$prevOptionId] = $this->lastOptionTitle[$prevOptionId]; - unset($this->lastOptionTitle); + $titles[$prevOptionId] = $this->lastOptionTitle[$prevOptionId]; + unset($this->lastOptionTitle); } else { $titles[$prevOptionId][$defaultStoreId] = $rowData[self::COLUMN_TITLE]; } 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 fdbda7e817d56..9ef682e55f087 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -33,9 +33,9 @@ use Magento\ImportExport\Model\Import\Source\Csv; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap as BootstrapHelper; use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection; use Psr\Log\LoggerInterface; -use Magento\TestFramework\Helper\Bootstrap as BootstrapHelper; /** * Class ProductTest @@ -403,7 +403,7 @@ public function testSaveCustomOptionsWithMultipleStoreViews() $pathToFile = __DIR__ . '/_files/' . $importFile; $importModel = $this->createImportModel($pathToFile); $errors = $importModel->validateData(); - $this->assertTrue($errors->getErrorsCount() == 0); + $this->assertTrue($errors->getErrorsCount() == 0, 'Import File Validation Failed'); $importModel->importData(); /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -422,20 +422,41 @@ public function testSaveCustomOptionsWithMultipleStoreViews() $actualOptions = $actualData['options']; sort($expectedOptions); sort($actualOptions); - $this->assertEquals($expectedOptions, $actualOptions); + $this->assertEquals( + $expectedOptions, + $actualOptions, + 'Expected and actual options arrays does not match' + ); // assert of options data - $this->assertCount(count($expectedData['data']), $actualData['data']); - $this->assertCount(count($expectedData['values']), $actualData['values']); + $this->assertCount( + count($expectedData['data']), + $actualData['data'], + 'Expected and actual data count does not match' + ); + $this->assertCount( + count($expectedData['values']), + $actualData['values'], + 'Expected and actual values count does not match' + ); + foreach ($expectedData['options'] as $expectedId => $expectedOption) { $elementExist = false; // find value in actual options and values foreach ($actualData['options'] as $actualId => $actualOption) { if ($actualOption == $expectedOption) { $elementExist = true; - $this->assertEquals($expectedData['data'][$expectedId], $actualData['data'][$actualId]); + $this->assertEquals( + $expectedData['data'][$expectedId], + $actualData['data'][$actualId], + 'Expected data does not match actual data' + ); if (array_key_exists($expectedId, $expectedData['values'])) { - $this->assertEquals($expectedData['values'][$expectedId], $actualData['values'][$actualId]); + $this->assertEquals( + $expectedData['values'][$expectedId], + $actualData['values'][$actualId], + 'Expected values does not match actual data' + ); } unset($actualData['options'][$actualId]); // remove value in case of duplicating key values @@ -448,7 +469,11 @@ public function testSaveCustomOptionsWithMultipleStoreViews() // Make sure that after importing existing options again, option IDs and option value IDs are not changed $customOptionValues = $this->getCustomOptionValues($sku); $this->createImportModel($pathToFile)->importData(); - $this->assertEquals($customOptionValues, $this->getCustomOptionValues($sku)); + $this->assertEquals( + $customOptionValues, + $this->getCustomOptionValues($sku), + 'Option IDs changed after second import' + ); } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv index d4c4130e946a4..17858531993db 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_and_multiple_store_views.csv @@ -2,3 +2,7 @@ sku,website_code,store_view_code,attribute_set_code,product_type,name,descriptio simple,base,,Default,simple,New Product,,,9,1,"Catalog, Search","base,secondwebsite",,10,,,,Taxable Goods,new-product,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title,type=field,required=1,sku=1-text,price=100|name=Test Date and Time Title,type=date_time,required=1,sku=2-date,price=200|name=Test Select,type=drop_down,required=1,sku=3-1-select,price=310,option_title=Select Option 1|name=Test Select,type=drop_down,required=1,sku=3-2-select,price=320,option_title=Select Option 2|name=Test Checkbox,type=checkbox,required=1,sku=4-1-select,price=410,option_title=Checkbox Option 1|name=Test Checkbox,type=checkbox,required=1,sku=4-2-select,price=420,option_title=Checkbox Option 2|name=Test Radio,type=radio,required=1,sku=5-1-radio,price=510,option_title=Radio Option 1|name=Test Radio,type=radio,required=1,sku=5-2-radio,price=520,option_title=Radio Option 2",,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, simple,,default,Default,simple,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title_default,type=field,sku=1-text|name=Test Date and Time Title_default,type=date_time,sku=2-date|name=Test Select_default,type=drop_down,sku=3-1-select,option_title=Select Option 1_default|name=Test Select_default,type=drop_down,sku=3-2-select,option_title=Select Option 2_default|name=Test Checkbox_default,type=checkbox,sku=4-1-select,option_title=Checkbox Option 1_default|name=Test Checkbox_default,type=checkbox,sku=4-2-select,option_title=Checkbox Option 2_default|name=Test Radio_default,type=radio,sku=5-1-radio,option_title=Radio Option 1_default|name=Test Radio_default,type=radio,sku=5-2-radio,option_title=Radio Option 2_default",,,,,,,,,,,,,,,,,,,,,,,,,,, simple,,secondstore,Default,simple,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title_fixture_second_store,type=field,sku=1-text,price=101|name=Test Date and Time Title_fixture_second_store,type=date_time,sku=2-date,price=201|name=Test Select_fixture_second_store,type=drop_down,sku=3-1-select,price=311,option_title=Select Option 1_fixture_second_store|name=Test Select_fixture_second_store,type=drop_down,sku=3-2-select,price=321,option_title=Select Option 2_fixture_second_store|name=Test Checkbox_second_store,type=checkbox,sku=4-1-select,price=411,option_title=Checkbox Option 1_second_store|name=Test Checkbox_second_store,type=checkbox,sku=4-2-select,price=421,option_title=Checkbox Option 2_second_store|name=Test Radio_fixture_second_store,type=radio,sku=5-1-radio,price=511,option_title=Radio Option 1_fixture_second_store|name=Test Radio_fixture_second_store,type=radio,sku=5-2-radio,price=521,option_title=Radio Option 2_fixture_second_store",,,,,,,,,,,,,,,,,,,,,,,,,,, +newprod2,base,secondstore,Default,configurable,New Product 2,,,9,1,"Catalog, Search","base,secondwebsite",,10,,,,Taxable Goods,new-product-2,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, +newprod3,base,,Default,configurable,New Product 3,,,9,1,"Catalog, Search","base,secondwebsite",,10,,,,Taxable Goods,new-product-3,,,,,,,,,,,,,,,,,,,,,,,,"name=Line 1,type=field,max_characters=30,required=1,option_title=Line 1|name=Line 2,type=field,max_characters=30,required=0,option_title=Line 2",,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, +newprod4,base,secondstore,Default,configurable,New Product 4,,,9,1,"Catalog, Search","base,secondwebsite",,10,,,,Taxable Goods,new-product-4,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, +newprod5,base,,Default,configurable,New Product 5,,,9,1,"Catalog, Search","base,secondwebsite",,10,,,,Taxable Goods,new-product-5,,,,,,,,,,,,,,,,,,,,,,,,"name=Line 3,type=field,max_characters=30,required=1,option_title=Line 3|name=Line 4,type=field,max_characters=30,required=0,option_title=Line 4",,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, From 345acd1375edc0674fb5cc805e83c1aa22a202d4 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 26 Jan 2020 00:08:59 +0530 Subject: [PATCH 283/666] Covered admin cms block creatation with MFTF test --- .../Mftf/Test/AdminCreateCmsBlockTest.xml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index ef4a7575c35d3..6388e89b46a5a 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -49,4 +49,36 @@ <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnGrid"/> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> + <test name="AdminCreateCmsBlockTest"> + <annotations> + <features value="Cms"/> + <stories value="CMS Block Creation and Reset Removal"/> + <title value="Admin should be able to create a CMS block"/> + <description value="Admin should be able to create a CMS block"/> + <severity value="CRITICAL"/> + <group value="Cms"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + </before> + <after> + <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> + <argument name="Block" value="_defaultBlock"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <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--> + <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> + <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> + <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose" /> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnForm"/> + </test> </tests> From a7a619aa42527bdb0849edd8f2229588b496eca7 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 26 Jan 2020 16:04:49 +0530 Subject: [PATCH 284/666] Action group added and MFTF test moved to seperate file --- ...rifyCmsBlockSaveSplitButtonActionGroup.xml | 23 ++++++++++++ .../Mftf/Test/AdminCreateCmsBlockTest.xml | 34 +----------------- .../Test/AdminSaveAndCloseCmsBlockTest.xml | 36 +++++++++++++++++++ 3 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml new file mode 100644 index 0000000000000..fee2f984c42d2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.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="VerifyCmsBlockSaveSplitButtonActionGroup"> + <annotations> + <description>verify Save and Close and Save and Duplicate button.</description> + </annotations> + + <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"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index 6388e89b46a5a..131e467f021c8 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -49,36 +49,4 @@ <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnGrid"/> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> - <test name="AdminCreateCmsBlockTest"> - <annotations> - <features value="Cms"/> - <stories value="CMS Block Creation and Reset Removal"/> - <title value="Admin should be able to create a CMS block"/> - <description value="Admin should be able to create a CMS block"/> - <severity value="CRITICAL"/> - <group value="Cms"/> - </annotations> - <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - </before> - <after> - <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> - <argument name="Block" value="_defaultBlock"/> - </actionGroup> - <actionGroup ref="logout" stepKey="logout"/> - </after> - <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--> - <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> - <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> - <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose" /> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnForm"/> - </test> -</tests> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml new file mode 100644 index 0000000000000..8c89c47ab5077 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.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="AdminSaveAndCloseCmsBlockTest"> + <annotations> + <features value="Cms"/> + <stories value="CMS Block Creation and Reset Removal"/> + <title value="Admin should be able to create a CMS block"/> + <description value="Admin should be able to create a CMS block using save and close"/> + <severity value="CRITICAL"/> + <group value="Cms"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + </before> + <after> + <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> + <argument name="Block" value="_defaultBlock"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!-- Navigate to create cms block page and verify save split button --> + <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="verifyCmsBlockSaveSplitButton" /> + <!--Create new CMS Block page--> + <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> + <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveCmsBlockContent" /> + </test> +</tests> \ No newline at end of file From 4e575713ce861e1aa08170081f2ace57f27029e3 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 26 Jan 2020 22:14:51 +0530 Subject: [PATCH 285/666] Added action group for cms block duplication test --- ...cateCMSBlockWithSplitButtonActionGroup.xml | 23 +++++++++++++++++++ ...rifyCmsBlockSaveSplitButtonActionGroup.xml | 23 +++++++++++++++++++ .../Mftf/Test/AdminCreateCmsBlockTest.xml | 21 ++++++----------- 3 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndDuplicateCMSBlockWithSplitButtonActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndDuplicateCMSBlockWithSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndDuplicateCMSBlockWithSplitButtonActionGroup.xml new file mode 100644 index 0000000000000..625046d1a978b --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndDuplicateCMSBlockWithSplitButtonActionGroup.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="SaveAndDuplicateCMSBlockWithSplitButtonActionGroup"> + <annotations> + <description>Clicks on the Save and Duplicate button.</description> + </annotations> + + <waitForElementVisible selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="waitForExpandSplitButtonToBeVisible"/> + <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitButton"/> + <click selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> + <waitForPageLoad stepKey="waitForPageLoadAfterClickingSave"/> + <see userInput="You saved the block." stepKey="assertSaveBlockSuccessMessage"/> + <see userInput="You duplicated the block." stepKey="seeDuplicatedBlockMsg"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.xml new file mode 100644 index 0000000000000..fee2f984c42d2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCmsBlockSaveSplitButtonActionGroup.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="VerifyCmsBlockSaveSplitButtonActionGroup"> + <annotations> + <description>verify Save and Close and Save and Duplicate button.</description> + </annotations> + + <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"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index ef4a7575c35d3..6867560551915 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -28,25 +28,18 @@ </actionGroup> <actionGroup ref="logout" stepKey="logout"/> </after> - <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"/> + <!-- Navigate to create cms block page and verify save split button --> + <actionGroup ref="VerifyCmsBlockSaveSplitButtonActionGroup" stepKey="verifyCmsBlockSaveButton" /> <!--Create new CMS Block page--> <actionGroup ref="FillOutBlockContent" stepKey="FillOutBlockContent"/> - <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn2" /> - <click selector="{{BlockNewPagePageActionsSection.saveAndDuplicate}}" stepKey="clickSaveAndDuplicate" /> - <waitForPageLoad stepKey="waitForPageLoad3"/> - <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnForm"/> - <see userInput="You duplicated the block." stepKey="seeDuplicatedBlockMsg"/> + <!-- Click save and duplicate action --> + <actionGroup ref="SaveAndDuplicateCMSBlockWithSplitButtonActionGroup" stepKey="clickSaveAndDuplicateButton" /> + <!--Verify duplicated CMS Block Page--> <seeElement selector="{{BlockNewPageBasicFieldsSection.isActive('0')}}" stepKey="seeBlockNotEnable" /> <actionGroup ref="AssertBlockContent" stepKey="assertContent"/> - <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn3" /> - <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose"/> - <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnGrid"/> + <!-- Click save and close button --> + <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveAndCloseAction" /> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> </tests> From e543d0a6c5580ae11e65e5789118d33dc9f47624 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Sun, 26 Jan 2020 19:20:26 +0200 Subject: [PATCH 286/666] Replace dataProvider with separate methods --- .../Test/Unit/Observer/EventSaverTest.php | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php index 8175887a33903..eebed5bfc0431 100644 --- a/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php +++ b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php @@ -116,41 +116,30 @@ public function testSaveWithSubject() } /** - * Test save with no subject ID provided - * - * @param bool $isLoggedIn - * @dataProvider dataProviderTestSaveWithoutSubject + * Test save with no subject ID provided and customer is logged in */ - public function testSaveWithoutSubject(bool $isLoggedIn) + public function testSaveWithoutSubjectWhenLoggedIn() { - if ($isLoggedIn) { - $this->customerSessionMock->expects($this->once()) - ->method('isLoggedIn') - ->willReturn(true); - $this->customerSessionMock->expects($this->once()) - ->method('getCustomerId') - ->willReturn(1); - } else { - $this->customerSessionMock->expects($this->once()) - ->method('isLoggedIn') - ->willReturn(false); - $this->customerVisitorMock->expects($this->once()) - ->method('getId') - ->willReturn(2); - } + $this->customerSessionMock->expects($this->once()) + ->method('isLoggedIn') + ->willReturn(true); + $this->customerSessionMock->expects($this->once()) + ->method('getCustomerId') + ->willReturn(1); $this->eventSaver->save(1, 1, null); } /** - * Data provider for a case without subjectId provided - * - * @return array + * Test save with no subject ID provided and customer is not logged in */ - public function dataProviderTestSaveWithoutSubject() + public function testSaveWithoutSubjectForGuest() { - return [ - [true], - [false] - ]; + $this->customerSessionMock->expects($this->once()) + ->method('isLoggedIn') + ->willReturn(false); + $this->customerVisitorMock->expects($this->once()) + ->method('getId') + ->willReturn(2); + $this->eventSaver->save(1, 1, null); } } From a17c2a51d226f810ddc5bf32a7b28b23b6b59ea2 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Mon, 27 Jan 2020 01:10:23 +0530 Subject: [PATCH 287/666] More jasmine tests added --- .../Ui/base/js/grid/data-storage.test.js | 434 +++++++++++++++++- 1 file changed, 418 insertions(+), 16 deletions(-) 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 454fc1280c548..f595020673ed7 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 @@ -62,13 +62,13 @@ define([ }); }); - describe('"getByIds"', function() { + describe('"getByIds" method', function () { var model = new DataStorage({ dataScope: 'magento' }); - it('check for defined', function() { + it('check for defined', function () { expect(model.hasOwnProperty('getByIds')).toBeDefined(); }); @@ -78,23 +78,198 @@ define([ it('Check returned value if method called with argument', function () { var ids = [1,2,3]; + expect(model.getByIds(ids)).toBeDefined(); }); - it('check returned false if method called with argument', function() { - var ids = [1,2,3]; - var type = typeof model.getByIds(ids); + it('check returned type if method called with argument', function () { + var ids = [1,2,3], + type = typeof model.getByIds(ids); + expect(type).toEqual('boolean'); }); - it('Return false', function() { + it('Return false if "getByIds" has been called', function () { + var ids = [1,2,3]; + + expect(model.getByIds(ids)).toEqual(false); + }); + + it('Return array if "getByIds" has been called', function () { + var ids = [1]; + + model = new DataStorage({ + dataScope: 'magento', + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1' + } + } + }); + + expect(typeof model.getByIds(ids)).toEqual('object'); + }); + + }); + + describe('"getIds" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function () { + expect(model.hasOwnProperty('getIds')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getIds).toEqual('function'); + }); + + it('check returned value if method called with argument', function () { var ids = [1,2,3]; - expect(model.getByIds(ids)).toEqual('false'); + + expect(model.getIds(ids)).toBeDefined(); + }); + + it('check returned type if method called with argument', function () { + var ids = [1,2,3], + type = typeof model.getIds(ids); + + expect(type).toEqual('object'); }); }); - describe('hasScopeChanged', function () { + describe('"getData" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('check for defined', function () { + expect(model.hasOwnProperty('getData')).toBeDefined(); + }); + + it('check method type', function () { + expect(typeof model.getData).toEqual('function'); + }); + + it('check returned value if method called with argument', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + expect(model.getData(params)).toBeDefined(); + }); + + it('check returned type if method called with argument', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + type = typeof model.getData(params); + + expect(type).toEqual('object'); + }); + + it('check "clearRequests" has been called', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + spyOn(model, 'clearRequests'); + spyOn(model, 'hasScopeChanged').and.callFake(function () { + return true; + }); + model.getData(params); + expect(model.clearRequests).toHaveBeenCalled(); + }); + + it('check "getRequest" has been called', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }; + + spyOn(model, 'getRequest'); + spyOn(model, 'hasScopeChanged').and.callFake(function () { + return false; + }); + model.getData(params); + expect(model.getRequest).toHaveBeenCalled(); + }); + + it('Return "getRequestData" method', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + options = { + refresh: false + }; + + spyOn(model, 'getRequestData'); + spyOn(model, 'getRequest').and.callFake(function () { + return true; + }); + model.getData(params, options); + expect(model.getRequestData).toHaveBeenCalled(); + }); + + it('Return "requestData" method', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + options = { + refresh: true + }; + + spyOn(model, 'requestData'); + spyOn(model, 'getRequest').and.callFake(function () { + return false; + }); + model.getData(params, options); + expect(model.requestData).toHaveBeenCalled(); + }); + + }); + + describe('"hasScopeChanged" method', function () { it('is function', function () { var model = new DataStorage({ dataScope: '' @@ -144,10 +319,37 @@ define([ expect(model.hasScopeChanged(newParams)).toBeTruthy(); }); }); + + describe('"updateData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('updateData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.updateData; + + expect(type).toEqual('function'); + }); + + it('Check updateData has been called', function () { + var data = [{ + id_field_name: 'entity_id', + entity_id: '1' + }]; + + expect(model.updateData(data)).toBeTruthy(); + }); + }); + describe('"getRequestData" method', function () { var model = new DataStorage({ dataScope: 'magento' }); + it('Check for defined ', function () { expect(model.hasOwnProperty('getRequestData')).toBeDefined(); }); @@ -162,6 +364,7 @@ define([ var request = { ids: [1,2,3] }; + expect(model.getRequestData(request)).toBeTruthy(); }); }); @@ -170,6 +373,7 @@ define([ var model = new DataStorage({ dataScope: 'magento' }); + it('Check for defined ', function () { expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); }); @@ -180,19 +384,217 @@ define([ expect(type).toEqual('function'); }); - it('check "cacheRequest" has been executed', function () { - var data = { - items: [1,2,3], - totalRecords: 3, - errorMessage: '' - }, - params = { + it('check "model._requests"', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + data = { + items: ['1','2','3'], + totalRecords: 3 + }; + + spyOn(model, 'removeRequest'); + spyOn(model, 'getIds').and.callFake(function () { + return ['1','2','3']; + }); + model.cacheRequest(data, params); + expect(typeof model._requests).toEqual('object'); + expect(model.getIds).toHaveBeenCalled(); + expect(model.removeRequest).not.toHaveBeenCalled(); + }); + + it('check "removeRequest" is executed', function () { + var params = { namespace: 'magento', search: '', sorting: {}, paging: {} + }, + data = { + items: ['1','2','3'], + totalRecords: 3 }; - expect(model.cacheRequest(data, params)).toBeTruthy(); + + spyOn(model, 'removeRequest'); + spyOn(model, 'getRequest').and.callFake(function () { + return true; + }); + spyOn(model, 'getIds').and.callFake(function () { + return ['1','2','3']; + }); + model.cacheRequest(data, params); + expect(typeof model._requests).toEqual('object'); + expect(model.getIds).toHaveBeenCalled(); + expect(model.removeRequest).toHaveBeenCalled(); + }); + }); + + describe('"clearRequests" method', function () { + + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('clearRequests')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.clearRequests; + + expect(type).toEqual('function'); + }); + + it('check "clearRequests" will empty _requests array', function () { + var params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }; + + model = new DataStorage({ + dataScope: 'magento', + _requests: [] + }); + + 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({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('removeRequest')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.removeRequest; + + expect(type).toEqual('function'); + }); + + it('check "removeRequest" is defined', function () { + var params = { + namespace: 'magento', + search: 'magento', + filters: { + store_id: 1 + } + }, + request = [{ + ids: [1,2,3], + params: params, + totalRecords: 3, + errorMessage: 'errorMessage' + }]; + + expect(model.removeRequest(request)).toBeDefined(); + }); + }); + + describe('"wasRequested" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('wasRequested')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.wasRequested; + + expect(type).toEqual('function'); + }); + + it('Return false if getRequest method returns false', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model.wasRequested(params); + expect(model.wasRequested(params)).toBeFalsy(); + }); + }); + + describe('"onRequestComplete" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined ', function () { + expect(model.hasOwnProperty('onRequestComplete')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.onRequestComplete; + + expect(type).toEqual('function'); + }); + + it('Check "updateData" method has been called', function () { + var data = { + items: [{ + id_field_name: 'entity_id', + entity_id: '1' + }] + }, +params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + spyOn(model, 'updateData').and.callFake(function () { + return data; + }); + model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); + }); + + it('Check "cacheRequest" method has been called', function () { + var data = { + items: [{ + id_field_name: 'entity_id', + entity_id: '1' + }] + }, + params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model = new DataStorage({ + dataScope: 'magento', + cacheRequests: true + }); + spyOn(model, 'cacheRequest').and.callFake(function () { + return data; + }); + model.onRequestComplete(params, data); + expect(model.cacheRequest).toHaveBeenCalled(); }); }); }); From fee5a139f2fe36c0c852a5592732c0f87a792187 Mon Sep 17 00:00:00 2001 From: Mayank <mayank@dolphinwebsolution.com> Date: Mon, 27 Jan 2020 12:20:15 +0530 Subject: [PATCH 288/666] Typo Mistake --- .../Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php index 50d29c195968c..3af058ef978cf 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php @@ -60,7 +60,7 @@ public function initTotals() { $parent = $this->getParentBlock(); $this->_source = $parent->getSource(); - $total = new \Magento\Framework\DataObject(['code' => 'agjustments', 'block_name' => $this->getNameInLayout()]); + $total = new \Magento\Framework\DataObject(['code' => 'adjustments', 'block_name' => $this->getNameInLayout()]); $parent->removeTotal('shipping'); $parent->removeTotal('adjustment_positive'); $parent->removeTotal('adjustment_negative'); From 51dff6e37c7abf6e9b4dd6a637caa9e0eb6574a7 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Mon, 27 Jan 2020 09:31:33 +0100 Subject: [PATCH 289/666] Add frontend template hints status command unit tests --- .../Command/TemplateHintsStatusCommand.php | 10 +-- .../TemplateHintsStatusCommandTest.php | 63 +++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 5905f951aa2a1..01c4fe42e083e 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -67,7 +67,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->reinitableConfig->reinit(); $templateHintsStatus = - ($this->isTemplateHintsEnabled()) + $this->scopeConfig->isSetFlag(self::TEMPLATE_HINTS_STOREFRONT_PATH, 'default') ? 'enabled' : 'disabled'; $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); @@ -75,12 +75,4 @@ protected function execute(InputInterface $input, OutputInterface $output) return Cli::RETURN_SUCCESS; } - - /** - * @return bool - */ - private function isTemplateHintsEnabled(): bool - { - return $this->scopeConfig->isSetFlag(self::TEMPLATE_HINTS_STOREFRONT_PATH, 'default'); - } } diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php new file mode 100644 index 0000000000000..27f41a61f9202 --- /dev/null +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Developer\Test\Unit\Console\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Tester\CommandTester; +use Magento\Developer\Console\Command\TemplateHintsStatusCommand; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\ReinitableConfigInterface; + +/** + * Class TemplateHintsStatusCommandTest + * + * Tests dev:template-hints:status command. + */ +class TemplateHintsStatusCommandTest extends TestCase +{ + /** + * @var TemplateHintsStatusCommand + */ + private $command; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfigMock; + /** + * @var ReinitableConfigInterface + */ + private $reinitableConfigMock; + + protected function setUp() + { + $this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class); + $this->reinitableConfigMock = $this->getMockForAbstractClass(ReinitableConfigInterface::class); + + $this->command = new TemplateHintsStatusCommand( + $this->scopeConfigMock, + $this->reinitableConfigMock + ); + + } + + public function testExecute() + { + $tester = new CommandTester($this->command); + $tester->execute([]); + + $this->assertContains( + 'disabled', + $tester->getDisplay() + ); + + $this->assertEquals( + 0, + $tester->getStatusCode() + ); + } +} \ No newline at end of file From 55e2e64e98583cab40b79f97e9c515c439efbe28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chitesh=40wagento=2Ecom=E2=80=9D?= <hitesh@wagento.com> Date: Mon, 27 Jan 2020 14:47:10 +0530 Subject: [PATCH 290/666] [fixed My Wish List Product not showing properly between >768px and <1023px] --- .../web/css/source/_module.less | 13 +++++++++++++ .../web/css/source/_module.less | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less index 9cd0439c13956..b26abd2731131 100644 --- a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less @@ -53,6 +53,17 @@ } } + .products-grid.wishlist { + .product-item { + margin-left: 2%; + padding: 5px; + width: calc(~'(100% - 4%) / 3'); + &:nth-child(3n + 1) { + margin-left: 0; + } + } + } + .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -185,6 +196,8 @@ .products-grid.wishlist { .product-item { border-bottom: 1px solid @secondary__color; + margin: 0; + width: 100%; &:first-child { border-top: 1px solid @secondary__color; } diff --git a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less index 85e8aeb0b515c..0c4be4dcd6c00 100644 --- a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less @@ -45,6 +45,17 @@ } } + .products-grid.wishlist { + .product-item { + margin-left: 2%; + padding: 5px; + width: calc(~'(100% - 4%) / 3'); + &:nth-child(3n + 1) { + margin-left: 0; + } + } + } + .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -183,7 +194,7 @@ } } .products-grid.wishlist { - .product-item-actions { + .product-item-actions { .action { &.edit, &.delete { @@ -216,7 +227,8 @@ .products-grid.wishlist { .product-item { border-bottom: 1px solid @secondary__color; - + margin: 0; + width: 100%; &:first-child { border-top: 1px solid @secondary__color; } @@ -253,7 +265,7 @@ &:last-child { margin-right: 0; } - + &.edit, &.delete { margin-top: 7px; From 0c00764f9fd1943da2620d7916c560a8d2ec98bc Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 27 Jan 2020 11:22:47 +0200 Subject: [PATCH 291/666] MC-30672: [Magento Cloud] Product Import Error --- app/code/Magento/CatalogImportExport/Model/Import/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index f7b15c9330fc5..ae5f0f5d79e2a 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -2521,7 +2521,7 @@ public function validateRow(array $rowData, $rowNum) $this->addRowError( ValidatorInterface::ERROR_DUPLICATE_URL_KEY, $rowNum, - $rowData[self::COL_NAME], + $urlKey, $message, $errorLevel ) From faf522f6dc56d8a87a913688e0f16d945d79f599 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Mon, 27 Jan 2020 13:12:35 +0200 Subject: [PATCH 292/666] Cover unit test --- .../Model/Checkout/Type/MultishippingTest.php | 295 ++++++++++++++++-- 1 file changed, 262 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index fba3245bec68d..c3f0f1113fb5a 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -3,34 +3,40 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Multishipping\Test\Unit\Model\Checkout\Type; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Type\Simple; use Magento\Checkout\Model\Session; use Magento\Customer\Api\AddressRepositoryInterface; use Magento\Customer\Api\Data\AddressInterface; use Magento\Customer\Api\Data\AddressSearchResultsInterface; use Magento\Customer\Api\Data\CustomerInterface; -use Magento\Directory\Model\Currency; -use Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderDefault; -use Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderFactory; -use Magento\Quote\Model\Quote\Address; use Magento\Customer\Model\Session as CustomerSession; +use Magento\Directory\Model\AllowedCountries; +use Magento\Directory\Model\Currency; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\SearchCriteria; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Framework\Session\Generic; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Multishipping\Helper\Data; use Magento\Multishipping\Model\Checkout\Type\Multishipping; +use Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderDefault; +use Magento\Multishipping\Model\Checkout\Type\Multishipping\PlaceOrderFactory; +use Magento\Payment\Model\Method\AbstractMethod; use Magento\Payment\Model\Method\SpecificationInterface; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Api\Data\CartExtension; use Magento\Quote\Api\Data\CartExtensionFactory; use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address as QuoteAddress; use Magento\Quote\Model\Quote\Address\Item as AddressItem; use Magento\Quote\Model\Quote\Address\ToOrder; @@ -38,22 +44,24 @@ use Magento\Quote\Model\Quote\AddressFactory; use Magento\Quote\Model\Quote\Item; use Magento\Quote\Model\Quote\Item\ToOrderItem; +use Magento\Quote\Model\Quote\Payment; use Magento\Quote\Model\Quote\Payment\ToOrderPayment; use Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentProcessor; use Magento\Quote\Model\Quote\TotalsCollector; use Magento\Quote\Model\Shipping; use Magento\Quote\Model\ShippingAssignment; +use Magento\Sales\Api\Data\OrderAddressInterface; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order\Email\Sender\OrderSender; use Magento\Sales\Model\OrderFactory; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use PHPUnit_Framework_MockObject_MockObject; -use \PHPUnit\Framework\TestCase; -use Magento\Quote\Model\Quote\Payment; -use Magento\Payment\Model\Method\AbstractMethod; -use Magento\Directory\Model\AllowedCountries; /** + * Test class Multishipping + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) */ @@ -174,6 +182,9 @@ class MultishippingTest extends \PHPUnit\Framework\TestCase */ private $scopeConfigMock; + /** + * @inheritDoc + */ protected function setUp() { $this->checkoutSessionMock = $this->createSimpleMock(Session::class); @@ -265,7 +276,13 @@ protected function setUp() ); } - public function testSetShippingItemsInformation() + /** + * Verify set shipping items information. + * + * @return void + * @throws LocalizedException + */ + public function testSetShippingItemsInformation():void { $info = [ [ @@ -313,10 +330,13 @@ public function testSetShippingItemsInformation() } /** - * @expectedException \Magento\Framework\Exception\LocalizedException + * Verefi set shipping items information for address leak + * + * @return void + * @expectedException LocalizedException * @expectedExceptionMessage Verify the shipping address information and continue. */ - public function testSetShippingItemsInformationForAddressLeak() + public function testSetShippingItemsInformationForAddressLeak():void { $info = [ [ @@ -343,7 +363,13 @@ public function testSetShippingItemsInformationForAddressLeak() $this->assertEquals($this->model, $this->model->setShippingItemsInformation($info)); } - public function testUpdateQuoteCustomerShippingAddress() + /** + * Verify update quote customer shipping address. + * + * @return void + * @throws LocalizedException + */ + public function testUpdateQuoteCustomerShippingAddress():void { $addressId = 42; $customerAddressId = 42; @@ -359,10 +385,13 @@ public function testUpdateQuoteCustomerShippingAddress() } /** - * @expectedException \Magento\Framework\Exception\LocalizedException + * Verify update quote customer shipping address for address leak + * + * @return void + * @expectedException LocalizedException * @expectedExceptionMessage Verify the shipping address information and continue. */ - public function testUpdateQuoteCustomerShippingAddressForAddressLeak() + public function testUpdateQuoteCustomerShippingAddressForAddressLeak():void { $addressId = 43; $customerAddressId = 42; @@ -375,7 +404,13 @@ public function testUpdateQuoteCustomerShippingAddressForAddressLeak() $this->assertEquals($this->model, $this->model->updateQuoteCustomerShippingAddress($addressId)); } - public function testSetQuoteCustomerBillingAddress() + /** + * Verify set quote customer billing address. + * + * @return void + * @throws LocalizedException + */ + public function testSetQuoteCustomerBillingAddress():void { $addressId = 42; $customerAddressId = 42; @@ -389,10 +424,13 @@ public function testSetQuoteCustomerBillingAddress() } /** - * @expectedException \Magento\Framework\Exception\LocalizedException + * Verify set quote customer billing address for address leak. + * + * @return void + * @expectedException LocalizedException * @expectedExceptionMessage Verify the billing address information and continue. */ - public function testSetQuoteCustomerBillingAddressForAddressLeak() + public function testSetQuoteCustomerBillingAddressForAddressLeak():void { $addressId = 43; $customerAddressId = 42; @@ -405,7 +443,12 @@ public function testSetQuoteCustomerBillingAddressForAddressLeak() $this->assertEquals($this->model, $this->model->setQuoteCustomerBillingAddress($addressId)); } - public function testGetQuoteShippingAddressesItems() + /** + * Verify get quote shipping addresses items. + * + * @return void + */ + public function testGetQuoteShippingAddressesItems():void { $quoteItem = $this->getMockBuilder(AddressItem::class) ->disableOriginalConstructor() @@ -415,7 +458,13 @@ public function testGetQuoteShippingAddressesItems() $this->model->getQuoteShippingAddressesItems(); } - public function testSetShippingMethods() + /** + * Verify set shipping methods + * + * @return void + * @throws LocalizedException + */ + public function testSetShippingMethods():void { $methodsArray = [1 => 'flatrate_flatrate', 2 => 'tablerate_bestway']; $addressId = 1; @@ -444,12 +493,15 @@ public function testSetShippingMethods() } /** + * Verify create orders + * * @return void + * @throws \Exception */ public function testCreateOrders(): void { $addressTotal = 5; - $productType = \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE; + $productType = Type::TYPE_SIMPLE; $infoBuyRequest = [ 'info_buyRequest' => [ 'product' => '1', @@ -460,7 +512,7 @@ public function testCreateOrders(): void $paymentProviderCode = 'checkmo'; $shippingPrice = '0.00'; $currencyCode = 'USD'; - $simpleProductTypeMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Type\Simple::class) + $simpleProductTypeMock = $this->getMockBuilder(Simple::class) ->disableOriginalConstructor() ->setMethods(['getOrderOptions']) ->getMock(); @@ -484,8 +536,8 @@ public function testCreateOrders(): void ->getMock(); $storeMock->method('getBaseCurrency')->willReturn($currencyMock); $storeMock->method('getCurrentCurrencyCode')->willReturn($currencyCode); - $orderAddressMock = $this->createSimpleMock(\Magento\Sales\Api\Data\OrderAddressInterface::class); - $orderPaymentMock = $this->createSimpleMock(\Magento\Sales\Api\Data\OrderPaymentInterface::class); + $orderAddressMock = $this->createSimpleMock(OrderAddressInterface::class); + $orderPaymentMock = $this->createSimpleMock(OrderPaymentInterface::class); $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class) ->disableOriginalConstructor() ->setMethods(['getQuoteItemId']) @@ -499,7 +551,7 @@ public function testCreateOrders(): void $this->orderFactoryMock->expects($this->once())->method('create')->willReturn($orderMock); $this->dataObjectHelperMock->expects($this->once())->method('mergeDataObjects') ->with( - \Magento\Sales\Api\Data\OrderInterface::class, + OrderInterface::class, $orderMock, $orderMock )->willReturnSelf(); @@ -517,6 +569,7 @@ public function testCreateOrders(): void )->willReturn($orderAddressMock); $this->toOrderPaymentMock->method('convert')->willReturn($orderPaymentMock); $this->toOrderItemMock->method('convert')->with($quoteAddressItemMock)->willReturn($orderItemMock); + $this->quoteMock->expects($this->once())->method('collectTotals')->willReturnSelf(); $placeOrderServiceMock = $this->getMockBuilder(PlaceOrderDefault::class) ->disableOriginalConstructor() @@ -530,6 +583,117 @@ public function testCreateOrders(): void } /** + * Create orders verify exception message + * + * @param array $config + * + * @return void + * @dataProvider getConfigCreateOrders + * @throws \Exception + */ + public function testCreateOrdersWithThrowsException(array $config): void + { + $simpleProductTypeMock = $this->getMockBuilder(Simple::class) + ->disableOriginalConstructor() + ->setMethods(['getOrderOptions']) + ->getMock(); + $productMock = $this->getProductMock($simpleProductTypeMock); + $simpleProductTypeMock->method('getOrderOptions') + ->with($productMock) + ->willReturn($config['infoBuyRequest']); + $quoteItemMock = $this->getQuoteItemMock($config['productType'], $productMock); + $quoteAddressItemMock = + $this->getQuoteAddressItemMock($quoteItemMock, $config['productType'], $config['infoBuyRequest']); + list($shippingAddressMock, $billingAddressMock) = + $this->getQuoteAddressesMock($quoteAddressItemMock, $config['addressTotal']); + $this->setQuoteMockData($config['paymentProviderCode'], $shippingAddressMock, $billingAddressMock); + $currencyMock = $this->getMockBuilder(Currency::class) + ->disableOriginalConstructor() + ->setMethods([ 'convert' ]) + ->getMock(); + $currencyMock->method('convert') + ->willReturn($config['shippingPrice']); + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getBaseCurrency','getCurrentCurrencyCode' ]) + ->getMock(); + $storeMock->method('getBaseCurrency') + ->willReturn($currencyMock); + $storeMock->method('getCurrentCurrencyCode') + ->willReturn($config['currencyCode']); + $orderAddressMock = $this->createSimpleMock(OrderAddressInterface::class); + $orderPaymentMock = $this->createSimpleMock(OrderPaymentInterface::class); + $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class) + ->disableOriginalConstructor() + ->setMethods(['getQuoteItemId']) + ->getMock(); + $orderItemMock->method('getQuoteItemId') + ->willReturn($config['quoteItemId']); + $orderMock = $this->getOrderMock($orderAddressMock, $orderPaymentMock, $orderItemMock); + $orderMock->expects($this->once()) + ->method('getStore') + ->willReturn($storeMock); + $orderMock->expects($this->once()) + ->method('setBaseShippingAmount') + ->with($config['shippingPrice'])->willReturnSelf(); + $orderMock->expects($this->once()) + ->method('setShippingAmount') + ->with($config['shippingPrice']) + ->willReturnSelf(); + $this->orderFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($orderMock); + $this->dataObjectHelperMock->expects($this->once()) + ->method('mergeDataObjects') + ->with( + OrderInterface::class, + $orderMock, + $orderMock + )->willReturnSelf(); + $this->priceMock->expects($this->once()) + ->method('round') + ->with($config['addressTotal']) + ->willReturn($config['addressTotal']); + $this->toOrderMock->expects($this->once()) + ->method('convert') + ->with($shippingAddressMock) + ->willReturn($orderMock); + $this->toOrderAddressMock->expects($this->exactly(2))->method('convert') + ->withConsecutive( + [$billingAddressMock, []], + [$shippingAddressMock, []] + )->willReturn($orderAddressMock); + $this->toOrderPaymentMock->method('convert') + ->willReturn($orderPaymentMock); + $this->toOrderItemMock->method('convert') + ->with($quoteAddressItemMock) + ->willReturn($orderItemMock); + $placeOrderServiceMock = $this->getMockBuilder(PlaceOrderDefault::class) + ->disableOriginalConstructor() + ->setMethods(['place']) + ->getMock(); + $placeOrderServiceMock->method('place') + ->with([$orderMock]) + ->willReturn([$config['quoteId'] => new \Exception()]); + $this->quoteMock->expects($this->any()) + ->method('__call') + ->willReturnSelf(); + $this->placeOrderFactoryMock->method('create') + ->with($config['paymentProviderCode']) + ->willReturn($placeOrderServiceMock); + $this->quoteMock->expects($this->exactly(2)) + ->method('collectTotals') + ->willReturnSelf(); + $this->quoteRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->quoteMock); + $this->expectExceptionMessage('Quote address for failed order ID "1" not found.'); + $this->model->createOrders(); + } + + /** + * Return Payment Mock. + * * @param string $paymentProviderCode * @return PHPUnit_Framework_MockObject_MockObject */ @@ -552,7 +716,9 @@ private function getPaymentMock(string $paymentProviderCode): PHPUnit_Framework_ } /** - * @param \Magento\Catalog\Model\Product\Type\Simple|PHPUnit_Framework_MockObject_MockObject $simpleProductTypeMock + * Return Product Mock. + * + * @param Simple|PHPUnit_Framework_MockObject_MockObject $simpleProductTypeMock * @return PHPUnit_Framework_MockObject_MockObject */ private function getProductMock($simpleProductTypeMock): PHPUnit_Framework_MockObject_MockObject @@ -567,6 +733,8 @@ private function getProductMock($simpleProductTypeMock): PHPUnit_Framework_MockO } /** + * Return Quote Item Mock. + * * @param string $productType * @param \Magento\Catalog\Model\Product|PHPUnit_Framework_MockObject_MockObject $productMock * @return PHPUnit_Framework_MockObject_MockObject @@ -584,6 +752,8 @@ private function getQuoteItemMock($productType, $productMock): PHPUnit_Framework } /** + * Return Quote Address Item Mock + * * @param \Magento\Quote\Model\Quote\Item|PHPUnit_Framework_MockObject_MockObject $quoteItemMock * @param string $productType * @param array $infoBuyRequest @@ -607,6 +777,7 @@ private function getQuoteAddressItemMock( } /** + * Return Quote Addresses Mock * @param \Magento\Quote\Model\Quote\Address\Item|PHPUnit_Framework_MockObject_MockObject $quoteAddressItemMock * @param int $addressTotal * @return array @@ -650,6 +821,8 @@ private function getQuoteAddressesMock($quoteAddressItemMock, int $addressTotal) } /** + * Set data for Quote Mock. + * * @param string $paymentProviderCode * @param Address|PHPUnit_Framework_MockObject_MockObject $shippingAddressMock * @param Address|PHPUnit_Framework_MockObject_MockObject $billingAddressMock @@ -669,14 +842,15 @@ private function setQuoteMockData(string $paymentProviderCode, $shippingAddressM $this->quoteMock->method('hasVirtualItems') ->willReturn(false); $this->quoteMock->expects($this->once())->method('reserveOrderId')->willReturnSelf(); - $this->quoteMock->expects($this->once())->method('collectTotals')->willReturnSelf(); $this->quoteMock->method('getId')->willReturn($quoteId); $this->quoteMock->method('setIsActive')->with(false)->willReturnSelf(); } /** - * @param \Magento\Sales\Api\Data\OrderAddressInterface|PHPUnit_Framework_MockObject_MockObject $orderAddressMock - * @param \Magento\Sales\Api\Data\OrderPaymentInterface|PHPUnit_Framework_MockObject_MockObject $orderPaymentMock + * Return Order Mock. + * + * @param OrderAddressInterface|PHPUnit_Framework_MockObject_MockObject $orderAddressMock + * @param OrderPaymentInterface|PHPUnit_Framework_MockObject_MockObject $orderPaymentMock * @param \Magento\Sales\Model\Order\Item|PHPUnit_Framework_MockObject_MockObject $orderItemMock * @return PHPUnit_Framework_MockObject_MockObject */ @@ -696,6 +870,7 @@ private function getOrderMock( 'addItem', 'getIncrementId', 'getId', + 'getEntityId', 'getCanSendNewEmailFlag', 'getItems', 'setShippingMethod', @@ -712,6 +887,7 @@ private function getOrderMock( $orderMock->method('addItem')->with($orderItemMock)->willReturnSelf(); $orderMock->method('getIncrementId')->willReturn('1'); $orderMock->method('getId')->willReturn('1'); + $orderMock->method('getEntityId')->willReturn('1'); $orderMock->method('getCanSendNewEmailFlag')->willReturn(false); $orderMock->method('getItems')->willReturn([$orderItemMock]); @@ -721,10 +897,12 @@ private function getOrderMock( /** * Tests exception for addresses with country id not in the allowed countries list. * - * @expectedException \Magento\Framework\Exception\LocalizedException + * @return void + * @expectedException LocalizedException * @expectedExceptionMessage Some addresses can't be used due to the configurations for specific countries. + * @throws \Exception */ - public function testCreateOrdersCountryNotPresentInAllowedListException() + public function testCreateOrdersCountryNotPresentInAllowedListException():void { $abstractMethod = $this->getMockBuilder(AbstractMethod::class) ->disableOriginalConstructor() @@ -762,6 +940,8 @@ public function testCreateOrdersCountryNotPresentInAllowedListException() } /** + * Return Extension Attributes Mock. + * * @param ShippingAssignment $shippingAssignmentMock * @return CartExtension|PHPUnit_Framework_MockObject_MockObject */ @@ -781,6 +961,8 @@ private function getExtensionAttributesMock(ShippingAssignment $shippingAssignme } /** + * Return Shipping Assignment Mock. + * * @return ShippingAssignment | PHPUnit_Framework_MockObject_MockObject */ private function getShippingAssignmentMock() @@ -801,7 +983,12 @@ private function getShippingAssignmentMock() return $shippingAssignmentMock; } - private function mockShippingAssignment() + /** + * Expected shipping assignment + * + * @return void + */ + private function mockShippingAssignment():void { $shippingAssignmentMock = $this->getShippingAssignmentMock(); @@ -825,6 +1012,8 @@ private function mockShippingAssignment() } /** + * Return Customer Address Mock + * * @param $customerAddressId * @return Address | PHPUnit_Framework_MockObject_MockObject */ @@ -842,6 +1031,8 @@ private function getCustomerAddressMock($customerAddressId) } /** + * Return Simple Mock. + * * @param string $className * @return PHPUnit_Framework_MockObject_MockObject */ @@ -852,7 +1043,12 @@ private function createSimpleMock($className) ->getMock(); } - public function testValidateMinimumAmountMultiAddressTrue() + /** + * Verify validate minimum amount multi address is true. + * + * @return void + */ + public function testValidateMinimumAmountMultiAddressTrue():void { $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], @@ -864,7 +1060,12 @@ public function testValidateMinimumAmountMultiAddressTrue() $this->assertFalse($this->model->validateMinimumAmount()); } - public function testValidateMinimumAmountMultiAddressFalse() + /** + * Verify validate minimum amount multi address is false. + * + * @return void + */ + public function testValidateMinimumAmountMultiAddressFalse():void { $addressMock = $this->createMock(\Magento\Quote\Model\Quote\Address::class); $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( @@ -884,4 +1085,32 @@ public function testValidateMinimumAmountMultiAddressFalse() $this->assertTrue($this->model->validateMinimumAmount()); } + + /** + * Data provider + * + * @return array + */ + public function getConfigCreateOrders(): array + { + return [ + [ + [ + 'quoteId' => 1, + 'addressTotal' => 5, + 'productType' => Type::TYPE_SIMPLE, + 'infoBuyRequest'=> [ + 'info_buyRequest' => [ + 'product' => '1', + 'qty' => 1, + ], + ], + 'quoteItemId' => 1, + 'paymentProviderCode' => 'checkmo', + 'shippingPrice' => '0.00', + 'currencyCode' => 'USD', + ] + ] + ]; + } } From 28d078c29122435ab3220c7aaf7a1d6004b657b0 Mon Sep 17 00:00:00 2001 From: vadim <vadim@example.com> Date: Mon, 27 Jan 2020 13:15:40 +0200 Subject: [PATCH 293/666] Unit test coverage --- .../Magento/Analytics/Test/Unit/Model/ConnectorTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Analytics/Test/Unit/Model/ConnectorTest.php b/app/code/Magento/Analytics/Test/Unit/Model/ConnectorTest.php index 714d0daf5c419..90f6fa1643660 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/ConnectorTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/ConnectorTest.php @@ -57,9 +57,13 @@ public function testExecute() } /** + * Executing non-existing command + * * @expectedException \Magento\Framework\Exception\NotFoundException + * @expectedExceptionMessage Command "register" was not found. + * @return void */ - public function testExecuteCommandNotFound() + public function testExecuteCommandNotFound(): void { $commandName = 'register'; $this->connector->execute($commandName); From 5b9b16309a87bcc826ae883dd5a1ea70f162c8b1 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Mon, 27 Jan 2020 16:51:48 +0530 Subject: [PATCH 294/666] [Fedex] covered model source generic by unit test & removed deprecated class --- .../Magento/Fedex/Model/Source/Generic.php | 9 +- .../Test/Unit/Model/Source/GenericTest.php | 94 +++++++++++++++++++ 2 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Fedex/Test/Unit/Model/Source/GenericTest.php diff --git a/app/code/Magento/Fedex/Model/Source/Generic.php b/app/code/Magento/Fedex/Model/Source/Generic.php index f245685ce0274..b624c5e5cea15 100644 --- a/app/code/Magento/Fedex/Model/Source/Generic.php +++ b/app/code/Magento/Fedex/Model/Source/Generic.php @@ -5,7 +5,7 @@ */ namespace Magento\Fedex\Model\Source; -class Generic implements \Magento\Framework\Option\ArrayInterface +class Generic implements \Magento\Framework\Data\OptionSourceInterface { /** * @var \Magento\Fedex\Model\Carrier @@ -36,9 +36,12 @@ public function toOptionArray() { $configData = $this->_shippingFedex->getCode($this->_code); $arr = []; - foreach ($configData as $code => $title) { - $arr[] = ['value' => $code, 'label' => $title]; + if($configData) { + foreach ($configData as $code => $title) { + $arr[] = ['value' => $code, 'label' => $title]; + } } + return $arr; } } diff --git a/app/code/Magento/Fedex/Test/Unit/Model/Source/GenericTest.php b/app/code/Magento/Fedex/Test/Unit/Model/Source/GenericTest.php new file mode 100644 index 0000000000000..ac63442124920 --- /dev/null +++ b/app/code/Magento/Fedex/Test/Unit/Model/Source/GenericTest.php @@ -0,0 +1,94 @@ +<?php + +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Fedex\Test\Unit\Model\Source; + +use Magento\Fedex\Model\Source\Generic; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Magento\Fedex\Model\Carrier; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for Magento\Fedex\Test\Unit\Model\Source\Generic + */ +class GenericTest extends TestCase +{ + /** + * @var Generic + */ + private $model; + + /** + * @var Carrier|MockObject + */ + private $shippingFedexMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->shippingFedexMock = $this->createMock(Carrier::class); + + $objectManager = new ObjectManagerHelper($this); + $this->model = $objectManager->getObject( + Generic::class, + [ + 'shippingFedex' => $this->shippingFedexMock + ] + ); + } + + /** + * Test toOptionArray + * + * @param string $code + * @param array|false $methods + * @param array $result + * @return void + * @dataProvider toOptionArrayDataProvider + */ + public function testToOptionArray($code, $methods, $result): void + { + $this->model->code = $code; + $this->shippingFedexMock->expects($this->once()) + ->method('getCode') + ->willReturn($methods); + + $this->assertEquals($result, $this->model->toOptionArray()); + } + + /** + * Data provider for testToOptionArray() + * + * @return array + */ + public function toOptionArrayDataProvider(): array + { + return [ + [ + 'method', + [ + 'FEDEX_GROUND' => __('Ground'), + 'FIRST_OVERNIGHT' => __('First Overnight') + ], + [ + ['value' => 'FEDEX_GROUND', 'label' => __('Ground')], + ['value' => 'FIRST_OVERNIGHT', 'label' => __('First Overnight')] + ] + ], + [ + '', + false, + [] + ] + ]; + } +} From 3e2ea3a54e0568e2971fee7df3591a54f40e8b7d Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Mon, 27 Jan 2020 13:44:37 +0200 Subject: [PATCH 295/666] rename ActionGroup --- ...AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml} | 2 +- .../VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/code/Magento/Newsletter/Test/Mftf/ActionGroup/{AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml => AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml} (91%) diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml similarity index 91% rename from app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml rename to app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml index 73fb9de740ba7..a6242797cf3c6 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.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="AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup"> + <actionGroup name="AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup"> <amOnPage url="{{AdminNewsletterConfigPage.url}}" stepKey="amOnNewsletterConfigPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> <click selector="{{AdminNewsletterConfigPageSubscriptionOptionsSection.allowGuestSubscription}}" stepKey="allowEdit"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml index f4dc370391b64..6565c2a167ba2 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml @@ -13,7 +13,7 @@ <!--Log in to Magento as admin.--> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!--Allow Guest Subscription NO--> - <actionGroup ref="AssertAdminNewsletterConfigFieldGuestNotAllowedActionGroup" stepKey="amOnNewsletterConfigField"/> + <actionGroup ref="AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup" stepKey="amOnNewsletterConfigField"/> <!--Log out from Magento admin.--> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </before> From 680021bc33d3e581bf5d66cbba73a1326caa1617 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Mon, 27 Jan 2020 17:40:38 +0530 Subject: [PATCH 296/666] Static test fix --- app/code/Magento/Fedex/Model/Source/Generic.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Fedex/Model/Source/Generic.php b/app/code/Magento/Fedex/Model/Source/Generic.php index b624c5e5cea15..ba747db9f4470 100644 --- a/app/code/Magento/Fedex/Model/Source/Generic.php +++ b/app/code/Magento/Fedex/Model/Source/Generic.php @@ -3,6 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + + /** + * Fedex generic source implementation + * + * @author Magento Core Team <core@magentocommerce.com> + */ namespace Magento\Fedex\Model\Source; class Generic implements \Magento\Framework\Data\OptionSourceInterface @@ -36,7 +42,7 @@ public function toOptionArray() { $configData = $this->_shippingFedex->getCode($this->_code); $arr = []; - if($configData) { + if ($configData) { foreach ($configData as $code => $title) { $arr[] = ['value' => $code, 'label' => $title]; } From 0340713d242b1126fd5962ef3fd7c4049c443efa Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Mon, 27 Jan 2020 18:11:02 +0530 Subject: [PATCH 297/666] Static test fix --- app/code/Magento/Fedex/Model/Source/Generic.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Fedex/Model/Source/Generic.php b/app/code/Magento/Fedex/Model/Source/Generic.php index ba747db9f4470..b1c1c0aedb863 100644 --- a/app/code/Magento/Fedex/Model/Source/Generic.php +++ b/app/code/Magento/Fedex/Model/Source/Generic.php @@ -1,16 +1,17 @@ <?php + /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - /** - * Fedex generic source implementation - * - * @author Magento Core Team <core@magentocommerce.com> - */ namespace Magento\Fedex\Model\Source; +/** + * Fedex generic source implementation + * + * @author Magento Core Team <core@magentocommerce.com> + */ class Generic implements \Magento\Framework\Data\OptionSourceInterface { /** From d6316cfe9c5ec70cf99689b26c452a2b28986a4e Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Mon, 27 Jan 2020 14:41:04 +0200 Subject: [PATCH 298/666] added minor changes --- ...VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml index 6565c2a167ba2..0780363b682cd 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml @@ -11,11 +11,11 @@ <test name="VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest"> <before> <!--Log in to Magento as admin.--> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <actionGroup ref="LoginActionGroup" stepKey="loginAsAdmin"/> <!--Allow Guest Subscription NO--> <actionGroup ref="AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup" stepKey="amOnNewsletterConfigField"/> <!--Log out from Magento admin.--> - <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </before> <actionGroup ref="StorefrontCreateNewSubscriberActionGroup" stepKey="createSubscriber"/> </test> From 49eceb82c67d6b589fd9dee0680d4eaf7d011967 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 27 Jan 2020 14:49:44 +0200 Subject: [PATCH 299/666] MC-30794: Recently Viewed products issues in does not work on store view level --- .../Catalog/Block/Ui/ProductViewCounter.php | 32 +++++++++++++++---- .../Catalog/CustomerData/CompareProducts.php | 28 ++++++++++++++-- .../Unit/Block/Ui/ProductViewCounterTest.php | 24 ++++++++++---- .../Unit/CustomerData/CompareProductsTest.php | 26 ++++++++++++--- .../Product/Listing/DataProvider.php | 16 +++++++++- .../ui_component/widget_recently_compared.xml | 1 + .../ui_component/widget_recently_viewed.xml | 1 + .../view/frontend/web/js/product/provider.js | 14 +++++--- .../js/product/storage/ids-storage-compare.js | 24 ++++++++++---- .../frontend/web/js/product/view/provider.js | 10 ++++-- .../Magento/Checkout/Block/Cart/Sidebar.php | 3 +- .../Test/Unit/Block/Cart/SidebarTest.php | 3 +- 12 files changed, 145 insertions(+), 37 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php b/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php index dd2e23e67f3d7..6d96ba8e1880e 100644 --- a/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php +++ b/app/code/Magento/Catalog/Block/Ui/ProductViewCounter.php @@ -6,15 +6,17 @@ namespace Magento\Catalog\Block\Ui; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\ProductRenderFactory; +use Magento\Catalog\Model\ProductRepository; use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorComposite; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\EntityManager\Hydrator; use Magento\Framework\Registry; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Url; use Magento\Framework\View\Element\Template; use Magento\Store\Model\Store; -use Magento\Catalog\Model\ProductRenderFactory; -use Magento\Catalog\Model\ProductRepository; -use Magento\Framework\EntityManager\Hydrator; use Magento\Store\Model\StoreManager; /** @@ -25,6 +27,7 @@ * * @api * @since 101.1.0 + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductViewCounter extends Template { @@ -68,6 +71,13 @@ class ProductViewCounter extends Template */ private $registry; + /** + * Core store config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + /** * @param Template\Context $context * @param ProductRepository $productRepository @@ -78,6 +88,8 @@ class ProductViewCounter extends Template * @param SerializerInterface $serialize * @param Url $url * @param Registry $registry + * @param ScopeConfigInterface|null $scopeConfig + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Template\Context $context, @@ -88,7 +100,8 @@ public function __construct( Hydrator $hydrator, SerializerInterface $serialize, Url $url, - Registry $registry + Registry $registry, + ?ScopeConfigInterface $scopeConfig = null ) { parent::__construct($context); $this->productRepository = $productRepository; @@ -99,6 +112,7 @@ public function __construct( $this->serialize = $serialize; $this->url = $url; $this->registry = $registry; + $this->scopeConfig = $scopeConfig ?? ObjectManager::getInstance()->get(ScopeConfigInterface::class); } /** @@ -116,6 +130,10 @@ public function getCurrentProductData() { /** @var ProductInterface $product */ $product = $this->registry->registry('product'); + $productsScope = $this->scopeConfig->getValue( + 'catalog/recently_products/scope', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE + ); /** @var Store $store */ $store = $this->storeManager->getStore(); @@ -123,7 +141,8 @@ public function getCurrentProductData() return $this->serialize->serialize([ 'items' => [], 'store' => $store->getId(), - 'currency' => $store->getCurrentCurrency()->getCode() + 'currency' => $store->getCurrentCurrency()->getCode(), + 'productCurrentScope' => $productsScope ]); } @@ -140,7 +159,8 @@ public function getCurrentProductData() $product->getId() => $data ], 'store' => $store->getId(), - 'currency' => $store->getCurrentCurrency()->getCode() + 'currency' => $store->getCurrentCurrency()->getCode(), + 'productCurrentScope' => $productsScope ]; return $this->serialize->serialize($currentProductData); diff --git a/app/code/Magento/Catalog/CustomerData/CompareProducts.php b/app/code/Magento/Catalog/CustomerData/CompareProducts.php index afbeab8c9070e..bdac4dfde64d1 100644 --- a/app/code/Magento/Catalog/CustomerData/CompareProducts.php +++ b/app/code/Magento/Catalog/CustomerData/CompareProducts.php @@ -6,7 +6,13 @@ namespace Magento\Catalog\CustomerData; use Magento\Customer\CustomerData\SectionSourceInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\LocalizedException; +/** + * Catalog Product Compare Widget + */ class CompareProducts implements SectionSourceInterface { /** @@ -24,23 +30,33 @@ class CompareProducts implements SectionSourceInterface */ private $outputHelper; + /** + * Core store config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + /** * @param \Magento\Catalog\Helper\Product\Compare $helper * @param \Magento\Catalog\Model\Product\Url $productUrl * @param \Magento\Catalog\Helper\Output $outputHelper + * @param ScopeConfigInterface|null $scopeConfig */ public function __construct( \Magento\Catalog\Helper\Product\Compare $helper, \Magento\Catalog\Model\Product\Url $productUrl, - \Magento\Catalog\Helper\Output $outputHelper + \Magento\Catalog\Helper\Output $outputHelper, + ?ScopeConfigInterface $scopeConfig = null ) { $this->helper = $helper; $this->productUrl = $productUrl; $this->outputHelper = $outputHelper; + $this->scopeConfig = $scopeConfig ?? ObjectManager::getInstance()->get(ScopeConfigInterface::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function getSectionData() { @@ -54,11 +70,18 @@ public function getSectionData() } /** + * Get the list of compared product items + * * @return array + * @throws LocalizedException */ protected function getItems() { $items = []; + $productsScope = $this->scopeConfig->getValue( + 'catalog/recently_products/scope', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE + ); /** @var \Magento\Catalog\Model\Product $item */ foreach ($this->helper->getItemCollection() as $item) { $items[] = [ @@ -66,6 +89,7 @@ protected function getItems() 'product_url' => $this->productUrl->getUrl($item), 'name' => $this->outputHelper->productAttribute($item, $item->getName(), 'name'), 'remove_url' => $this->helper->getPostDataRemove($item), + 'productScope' => $productsScope ]; } return $items; diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php index e7e8ab5ea91a7..85ab52384740d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Ui/ProductViewCounterTest.php @@ -6,19 +6,20 @@ namespace Magento\Catalog\Test\Unit\Block\Ui; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\Data\ProductRenderInterface; +use Magento\Catalog\Block\Ui\ProductViewCounter; +use Magento\Catalog\Model\ProductRenderFactory; use Magento\Catalog\Model\ProductRepository; use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorComposite; -use Magento\Catalog\Model\ProductRenderFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\EntityManager\Hydrator; +use Magento\Framework\Registry; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Url; use Magento\Framework\View\Element\Template\Context; -use Magento\Store\Model\StoreManager; use Magento\Store\Model\Store; -use Magento\Framework\Registry; -use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Api\Data\ProductRenderInterface; -use Magento\Catalog\Block\Ui\ProductViewCounter; +use Magento\Store\Model\StoreManager; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -70,6 +71,11 @@ class ProductViewCounterTest extends \PHPUnit\Framework\TestCase */ private $storeManagerMock; + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfigMock; + /** * @var ProductRenderFactory|\PHPUnit_Framework_MockObject_MockObject */ @@ -104,6 +110,9 @@ protected function setUp() $this->storeManagerMock = $this->getMockBuilder(StoreManager::class) ->disableOriginalConstructor() ->getMock(); + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->productViewCounter = new ProductViewCounter( $this->contextMock, @@ -114,7 +123,8 @@ protected function setUp() $this->hydratorMock, $this->serializeMock, $this->urlMock, - $this->registryMock + $this->registryMock, + $this->scopeConfigMock ); } diff --git a/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php b/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php index e30ddda0b70b9..6f5d927e333ec 100644 --- a/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/CustomerData/CompareProductsTest.php @@ -15,6 +15,7 @@ use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Url; use Magento\Catalog\Model\ResourceModel\Product\Compare\Item\Collection; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; class CompareProductsTest extends \PHPUnit\Framework\TestCase @@ -44,6 +45,11 @@ class CompareProductsTest extends \PHPUnit\Framework\TestCase */ private $objectManagerHelper; + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfigMock; + /** * @var array */ @@ -65,6 +71,9 @@ protected function setUp() $this->outputHelperMock = $this->getMockBuilder(Output::class) ->disableOriginalConstructor() ->getMock(); + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->objectManagerHelper = new ObjectManagerHelper($this); @@ -73,7 +82,8 @@ protected function setUp() [ 'helper' => $this->helperMock, 'productUrl' => $this->productUrlMock, - 'outputHelper' => $this->outputHelperMock + 'outputHelper' => $this->outputHelperMock, + 'scopeConfig' => $this->scopeConfigMock ] ); } @@ -109,6 +119,7 @@ private function prepareProductsWithCorrespondingMocks(array $dataSet) : array $urlMap = []; $outputMap = []; $helperMap = []; + $productScopeMap = []; $count = count($dataSet); @@ -119,6 +130,7 @@ private function prepareProductsWithCorrespondingMocks(array $dataSet) : array $outputMap[] = [$item, $data['name'], 'name', 'productName#' . $data['id']]; $helperMap[] = [$item, 'http://remove.url/' . $data['id']]; $urlMap[] = [$item, [], 'http://product.url/' . $data['id']]; + $productScopeMap[] = [$item, 'store-' . $data['id']]; } $this->productUrlMock->expects($this->exactly($count)) @@ -193,19 +205,22 @@ public function testGetSectionData() 'id' => 1, 'product_url' => 'http://product.url/1', 'name' => 'productName#1', - 'remove_url' => 'http://remove.url/1' + 'remove_url' => 'http://remove.url/1', + 'productScope' => null ], [ 'id' => 2, 'product_url' => 'http://product.url/2', 'name' => 'productName#2', - 'remove_url' => 'http://remove.url/2' + 'remove_url' => 'http://remove.url/2', + 'productScope' => null ], [ 'id' => 3, 'product_url' => 'http://product.url/3', 'name' => 'productName#3', - 'remove_url' => 'http://remove.url/3' + 'remove_url' => 'http://remove.url/3', + 'productScope' => null ] ] ], @@ -276,7 +291,8 @@ public function testGetSectionDataSingleItem() 'id' => 12345, 'product_url' => 'http://product.url/12345', 'name' => 'productName#12345', - 'remove_url' => 'http://remove.url/12345' + 'remove_url' => 'http://remove.url/12345', + 'productScope' => null ] ] ], diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/DataProvider.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/DataProvider.php index 4de0b94d06801..3289e4806df3a 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/DataProvider.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/DataProvider.php @@ -8,12 +8,14 @@ use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\Search\SearchCriteriaBuilder; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\View\Element\UiComponent\DataProvider\Reporting; use Magento\Store\Model\StoreManager; /** * Provide information about current store and currency for product listing ui component + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider { @@ -22,6 +24,13 @@ class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvi */ private $storeManager; + /** + * Core store config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + /** * @param string $name * @param Reporting $reporting @@ -56,6 +65,7 @@ public function __construct( $this->name = $name; $this->storeManager = $storeManager; + $this->scopeConfig = $data['config']['scopeConfig']; } /** @@ -65,9 +75,13 @@ public function getData() { $data = []; $store = $this->storeManager->getStore(); + $productsScope = $this->scopeConfig->getValue( + 'catalog/recently_products/scope', + \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE + ); $data['store'] = $store->getId(); $data['currency'] = $store->getCurrentCurrency()->getCode(); - + $data['productCurrentScope'] = $productsScope; return $data; } } diff --git a/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_compared.xml b/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_compared.xml index 7cced8bb613c3..b0a275f720670 100644 --- a/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_compared.xml +++ b/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_compared.xml @@ -32,6 +32,7 @@ <item name="namespace" xsi:type="string">recently_compared_product</item> <item name="provider" xsi:type="string">compare-products</item> </item> + <item name="scopeConfig" xsi:type="object">Magento\Framework\App\Config\ScopeConfigInterface</item> </item> </argument> </argument> diff --git a/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_viewed.xml b/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_viewed.xml index efad08eef8c12..2af3b1210b18b 100644 --- a/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_viewed.xml +++ b/app/code/Magento/Catalog/view/frontend/ui_component/widget_recently_viewed.xml @@ -31,6 +31,7 @@ <item name="identifiersConfig" xsi:type="array"> <item name="namespace" xsi:type="string">recently_viewed_product</item> </item> + <item name="scopeConfig" xsi:type="object">Magento\Framework\App\Config\ScopeConfigInterface</item> </item> </argument> </argument> diff --git a/app/code/Magento/Catalog/view/frontend/web/js/product/provider.js b/app/code/Magento/Catalog/view/frontend/web/js/product/provider.js index ca9381c45e2ab..f246a8e3a0f9f 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/product/provider.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/product/provider.js @@ -138,13 +138,17 @@ define([ filterIds: function (ids) { var _ids = {}, currentTime = new Date().getTime() / 1000, - currentProductIds = productResolver($('#product_addtocart_form')); + currentProductIds = productResolver($('#product_addtocart_form')), + productCurrentScope = this.data.productCurrentScope, + scopeId = productCurrentScope === 'store' ? window.checkout.storeId : + productCurrentScope === 'group' ? window.checkout.storeGroupId : + window.checkout.websiteId; - _.each(ids, function (id) { + _.each(ids, function (id, key) { if ( - currentTime - id['added_at'] < ~~this.idsStorage.lifetime && - !_.contains(currentProductIds, id['product_id']) && - (!id.hasOwnProperty('website_id') || id['website_id'] === window.checkout.websiteId) + currentTime - ids[key]['added_at'] < ~~this.idsStorage.lifetime && + !_.contains(currentProductIds, ids[key]['product_id']) && + (!id.hasOwnProperty('scope_id') || ids[key]['scope_id'] === scopeId) ) { _ids[id['product_id']] = id; diff --git a/app/code/Magento/Catalog/view/frontend/web/js/product/storage/ids-storage-compare.js b/app/code/Magento/Catalog/view/frontend/web/js/product/storage/ids-storage-compare.js index a904d8ed3b3da..bd92c5d452423 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/product/storage/ids-storage-compare.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/product/storage/ids-storage-compare.js @@ -67,14 +67,26 @@ define([ * @returns {Object} data */ prepareData: function (data) { - var result = {}; + var result = {}, + scopeId; _.each(data, function (item) { - result[item.id] = { - 'added_at': new Date().getTime() / 1000, - 'product_id': item.id, - 'website_id': window.checkout.websiteId - }; + if (typeof item.productScope !== 'undefined') { + scopeId = item.productScope === 'store' ? window.checkout.storeId : + item.productScope === 'group' ? window.checkout.storeGroupId : + window.checkout.websiteId; + + result[item.productScope + '-' + scopeId + '-' + item.id] = { + 'added_at': new Date().getTime() / 1000, + 'product_id': item.id, + 'scope_id': scopeId + }; + } else { + result[item.id] = { + 'added_at': new Date().getTime() / 1000, + 'product_id': item.id + }; + } }); return result; diff --git a/app/code/Magento/Catalog/view/frontend/web/js/product/view/provider.js b/app/code/Magento/Catalog/view/frontend/web/js/product/view/provider.js index f4ce882dd668b..5bcf57c035929 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/product/view/provider.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/product/view/provider.js @@ -85,13 +85,17 @@ define([ * @returns {Object} */ getIdentifiers: function () { - var result = {}; + var result = {}, + productCurrentScope = this.data.productCurrentScope, + scopeId = productCurrentScope === 'store' ? window.checkout.storeId : + productCurrentScope === 'group' ? window.checkout.storeGroupId : + window.checkout.websiteId; _.each(this.data.items, function (item, key) { - result[key] = { + result[productCurrentScope + '-' + scopeId + '-' + key] = { 'added_at': new Date().getTime() / 1000, 'product_id': key, - 'website_id': window.checkout.websiteId + 'scope_id': scopeId }; }, this); diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index c5e309df3cad6..147782e501ae4 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -83,7 +83,8 @@ public function getConfig() 'minicartMaxItemsVisible' => $this->getMiniCartMaxItemsCount(), 'websiteId' => $this->_storeManager->getStore()->getWebsiteId(), 'maxItemsToDisplay' => $this->getMaxItemsToDisplay(), - 'storeId' => $this->_storeManager->getStore()->getId() + 'storeId' => $this->_storeManager->getStore()->getId(), + 'storeGroupId' => $this->_storeManager->getStore()->getStoreGroupId() ]; } diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php index f69ced3b094c7..fdf63b4ebe1ed 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php @@ -145,7 +145,8 @@ public function testGetConfig() 'minicartMaxItemsVisible' => 3, 'websiteId' => 100, 'maxItemsToDisplay' => 8, - 'storeId' => null + 'storeId' => null, + 'storeGroupId' => null ]; $valueMap = [ From 2324d99cd740fd969413aa50096b24c054ecf653 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 27 Jan 2020 15:04:54 +0200 Subject: [PATCH 300/666] MC-30540: "CData section too big" error while accessing configurable product in backend --- .../View/TemplateEngine/Xhtml/Template.php | 13 ++-- .../TemplateEngine/Xhtml/TemplateTest.php | 67 +++++++++++++++++++ .../Unit/TemplateEngine/_files/simple.xml | 12 ++++ 3 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/Xhtml/TemplateTest.php create mode 100644 lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/_files/simple.xml diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php index e75c80777ec0c..64cdf543a7571 100644 --- a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php @@ -6,7 +6,7 @@ namespace Magento\Framework\View\TemplateEngine\Xhtml; /** - * Class Template + * XML Template Engine */ class Template { @@ -34,7 +34,7 @@ public function __construct( ) { $this->logger = $logger; $document = new \DOMDocument(static::XML_VERSION, static::XML_ENCODING); - $document->loadXML($content); + $document->loadXML($content, LIBXML_PARSEHUGE); $this->templateNode = $document->documentElement; } @@ -56,9 +56,12 @@ public function getDocumentElement() */ public function append($content) { - $newFragment = $this->templateNode->ownerDocument->createDocumentFragment(); - $newFragment->appendXML($content); - $this->templateNode->appendChild($newFragment); + $ownerDocument= $this->templateNode->ownerDocument; + $document = new \DOMDocument(); + $document->loadXml($content, LIBXML_PARSEHUGE); + $this->templateNode->appendChild( + $ownerDocument->importNode($document->documentElement, true) + ); } /** diff --git a/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/Xhtml/TemplateTest.php b/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/Xhtml/TemplateTest.php new file mode 100644 index 0000000000000..3a3a7de47fbab --- /dev/null +++ b/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/Xhtml/TemplateTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Framework\View\Test\Unit\TemplateEngine\Xhtml; + +use Magento\Framework\View\TemplateEngine\Xhtml\Template; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Test XML template engine + */ +class TemplateTest extends TestCase +{ + /** + * @var Template + */ + private $model; + + /** + * @inheritDoc + */ + protected function setUp() + { + parent::setUp(); + $this->model = new Template( + $this->getMockForAbstractClass(LoggerInterface::class), + file_get_contents(__DIR__ . '/../_files/simple.xml') + ); + } + + /** + * Test that xml content is correctly appended to the current element + */ + public function testAppend() + { + $body = <<<HTML +<body> + <h1>Home Page</h1> + <p>CMS homepage content goes here.</p> +</body> +HTML; + $expected = <<<HTML +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--><html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>Home Page + + +

Home Page

+

CMS homepage content goes here.

+ + +HTML; + + $this->model->append($body); + $this->assertEquals($expected, (string) $this->model); + } +} diff --git a/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/_files/simple.xml b/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/_files/simple.xml new file mode 100644 index 0000000000000..0c73702b572c0 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Test/Unit/TemplateEngine/_files/simple.xml @@ -0,0 +1,12 @@ + + + + + Home Page + + From 619ab67eccfb8623e6517c91a78dae417ea97089 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Mon, 27 Jan 2020 15:07:41 +0200 Subject: [PATCH 301/666] MC-30544: "updated_at" timestamp not updating for products updated via "Update Attribute" action --- .../Model/ResourceModel/Product/Action.php | 57 +++++++++++++++---- .../Eav/Model/Entity/AbstractEntity.php | 16 +++++- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Action.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Action.php index ca20f57c5d00e..d0a3af92126d3 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Action.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Action.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Model\ResourceModel\Product; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; /** @@ -14,6 +15,32 @@ */ class Action extends \Magento\Catalog\Model\ResourceModel\AbstractResource { + /** + * @var \Magento\Framework\Stdlib\DateTime\DateTime + */ + private $dateTime; + + /** + * @param \Magento\Eav\Model\Entity\Context $context + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Catalog\Model\Factory $modelFactory + * @param \Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface $uniqueValidator + * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime + * @param array $data + */ + public function __construct( + \Magento\Eav\Model\Entity\Context $context, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Catalog\Model\Factory $modelFactory, + \Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface $uniqueValidator, + \Magento\Framework\Stdlib\DateTime\DateTime $dateTime, + $data = [] + ) { + parent::__construct($context, $storeManager, $modelFactory, $data, $uniqueValidator); + + $this->dateTime = $dateTime; + } + /** * Initialize connection * @@ -43,6 +70,7 @@ public function updateAttributes($entityIds, $attrData, $storeId) $object = new \Magento\Framework\DataObject(); $object->setStoreId($storeId); + $attrData[ProductInterface::UPDATED_AT] = $this->dateTime->gmtDate(); $this->getConnection()->beginTransaction(); try { foreach ($attrData as $attrCode => $value) { @@ -95,7 +123,7 @@ protected function _saveAttributeValue($object, $attribute, $value) * for default store id * In this case we clear all not default values */ - if ($this->_storeManager->hasSingleStore()) { + if ($this->_storeManager->hasSingleStore() && !$attribute->isStatic()) { $storeId = $this->getDefaultStoreId(); $connection->delete( $table, @@ -107,17 +135,24 @@ protected function _saveAttributeValue($object, $attribute, $value) ); } - $data = new \Magento\Framework\DataObject( - [ - 'attribute_id' => $attribute->getAttributeId(), - 'store_id' => $storeId, - $this->getLinkField() => $entityId, - 'value' => $this->_prepareValueForSave($value, $attribute), - ] - ); + $data = $attribute->isStatic() + ? new \Magento\Framework\DataObject( + [ + $this->getLinkField() => $entityId, + $attribute->getAttributeCode() => $this->_prepareValueForSave($value, $attribute), + ] + ) + : new \Magento\Framework\DataObject( + [ + 'attribute_id' => $attribute->getAttributeId(), + 'store_id' => $storeId, + $this->getLinkField() => $entityId, + 'value' => $this->_prepareValueForSave($value, $attribute), + ] + ); $bind = $this->_prepareDataForTable($data, $table); - if ($attribute->isScopeStore()) { + if ($attribute->isScopeStore() || $attribute->isStatic()) { /** * Update attribute value for store */ @@ -143,6 +178,8 @@ protected function _saveAttributeValue($object, $attribute, $value) } /** + * Resolve entity id + * * @param int $entityId * @return int */ diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index 7649c89a07955..5b6252f2c0d6c 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -1021,6 +1021,8 @@ public function load($object, $entityId, $attributes = []) protected function loadAttributesMetadata($attributes) { $this->loadAttributesForObject($attributes); + + return $this; } /** @@ -1433,8 +1435,10 @@ protected function _processSaveData($saveData) $insertEntity = true; $entityTable = $this->getEntityTable(); $entityIdField = $this->getEntityIdField(); + // phpstan:ignore "Undefined variable" $entityId = $newObject->getId(); + // phpstan:ignore "Undefined variable" unset($entityRow[$entityIdField]); if (!empty($entityId) && is_numeric($entityId)) { $bind = ['entity_id' => $entityId]; @@ -1450,6 +1454,7 @@ protected function _processSaveData($saveData) /** * Process base row */ + // phpstan:ignore "Undefined variable" $entityObject = new DataObject($entityRow); $entityRow = $this->_prepareDataForTable($entityObject, $entityTable); if ($insertEntity) { @@ -1460,6 +1465,7 @@ protected function _processSaveData($saveData) $connection->insert($entityTable, $entityRow); $entityId = $connection->lastInsertId($entityTable); } + // phpstan:ignore "Undefined variable" $newObject->setId($entityId); } else { $where = sprintf('%s=%d', $connection->quoteIdentifier($entityIdField), $entityId); @@ -1472,6 +1478,7 @@ protected function _processSaveData($saveData) if (!empty($insert)) { foreach ($insert as $attributeId => $value) { $attribute = $this->getAttribute($attributeId); + // phpstan:ignore "Undefined variable" $this->_insertAttribute($newObject, $attribute, $value); } } @@ -1482,6 +1489,7 @@ protected function _processSaveData($saveData) if (!empty($update)) { foreach ($update as $attributeId => $v) { $attribute = $this->getAttribute($attributeId); + // phpstan:ignore "Undefined variable" $this->_updateAttribute($newObject, $attribute, $v['value_id'], $v['value']); } } @@ -1491,12 +1499,14 @@ protected function _processSaveData($saveData) */ if (!empty($delete)) { foreach ($delete as $table => $values) { + // phpstan:ignore "Undefined variable" $this->_deleteAttributes($newObject, $table, $values); } } $this->_processAttributeValues(); + // phpstan:ignore "Undefined variable" $newObject->isObjectNew(false); return $this; @@ -1573,7 +1583,7 @@ protected function _processAttributeValues() { $connection = $this->getConnection(); foreach ($this->_attributeValuesToSave as $table => $data) { - $connection->insertOnDuplicate($table, $data, ['value']); + $connection->insertOnDuplicate($table, $data, array_keys($data[0])); } foreach ($this->_attributeValuesToDelete as $table => $valueIds) { @@ -1607,7 +1617,9 @@ protected function _prepareValueForSave($value, AbstractAttribute $attribute) self::$_attributeBackendTables[$backendTable] = $this->getConnection()->describeTable($backendTable); } $describe = self::$_attributeBackendTables[$backendTable]; - return $this->getConnection()->prepareColumnValue($describe['value'], $value); + $columnName = $attribute->isStatic() ? $attribute->getAttributeCode() : 'value'; + + return $this->getConnection()->prepareColumnValue($describe[$columnName], $value); } /** From a70842f7d5420fd0590b3ebb1fe5737fa1db94a4 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Mon, 27 Jan 2020 15:29:29 +0200 Subject: [PATCH 302/666] Fix unit test --- .../Model/Checkout/Type/MultishippingTest.php | 235 +++++++++++------- 1 file changed, 147 insertions(+), 88 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index c3f0f1113fb5a..3948025fa0388 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -282,7 +282,7 @@ protected function setUp() * @return void * @throws LocalizedException */ - public function testSetShippingItemsInformation():void + public function testSetShippingItemsInformation(): void { $info = [ [ @@ -333,10 +333,9 @@ public function testSetShippingItemsInformation():void * Verefi set shipping items information for address leak * * @return void - * @expectedException LocalizedException - * @expectedExceptionMessage Verify the shipping address information and continue. + * @throws LocalizedException */ - public function testSetShippingItemsInformationForAddressLeak():void + public function testSetShippingItemsInformationForAddressLeak(): void { $info = [ [ @@ -360,6 +359,8 @@ public function testSetShippingItemsInformationForAddressLeak():void $this->helperMock->expects($this->once())->method('getMaximumQty')->willReturn(500); $this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses); + $this->expectExceptionMessage('Verify the shipping address information and continue.'); + $this->assertEquals($this->model, $this->model->setShippingItemsInformation($info)); } @@ -369,7 +370,7 @@ public function testSetShippingItemsInformationForAddressLeak():void * @return void * @throws LocalizedException */ - public function testUpdateQuoteCustomerShippingAddress():void + public function testUpdateQuoteCustomerShippingAddress(): void { $addressId = 42; $customerAddressId = 42; @@ -388,10 +389,9 @@ public function testUpdateQuoteCustomerShippingAddress():void * Verify update quote customer shipping address for address leak * * @return void - * @expectedException LocalizedException - * @expectedExceptionMessage Verify the shipping address information and continue. + * @throws LocalizedException */ - public function testUpdateQuoteCustomerShippingAddressForAddressLeak():void + public function testUpdateQuoteCustomerShippingAddressForAddressLeak(): void { $addressId = 43; $customerAddressId = 42; @@ -400,6 +400,7 @@ public function testUpdateQuoteCustomerShippingAddressForAddressLeak():void $this->getCustomerAddressMock($customerAddressId) ]; $this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses); + $this->expectExceptionMessage('Verify the shipping address information and continue.'); $this->assertEquals($this->model, $this->model->updateQuoteCustomerShippingAddress($addressId)); } @@ -410,7 +411,7 @@ public function testUpdateQuoteCustomerShippingAddressForAddressLeak():void * @return void * @throws LocalizedException */ - public function testSetQuoteCustomerBillingAddress():void + public function testSetQuoteCustomerBillingAddress(): void { $addressId = 42; $customerAddressId = 42; @@ -427,10 +428,9 @@ public function testSetQuoteCustomerBillingAddress():void * Verify set quote customer billing address for address leak. * * @return void - * @expectedException LocalizedException - * @expectedExceptionMessage Verify the billing address information and continue. + * @throws LocalizedException */ - public function testSetQuoteCustomerBillingAddressForAddressLeak():void + public function testSetQuoteCustomerBillingAddressForAddressLeak(): void { $addressId = 43; $customerAddressId = 42; @@ -439,6 +439,7 @@ public function testSetQuoteCustomerBillingAddressForAddressLeak():void $this->getCustomerAddressMock($customerAddressId) ]; $this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses); + $this->expectExceptionMessage('Verify the billing address information and continue.'); $this->assertEquals($this->model, $this->model->setQuoteCustomerBillingAddress($addressId)); } @@ -448,7 +449,7 @@ public function testSetQuoteCustomerBillingAddressForAddressLeak():void * * @return void */ - public function testGetQuoteShippingAddressesItems():void + public function testGetQuoteShippingAddressesItems(): void { $quoteItem = $this->getMockBuilder(AddressItem::class) ->disableOriginalConstructor() @@ -464,7 +465,7 @@ public function testGetQuoteShippingAddressesItems():void * @return void * @throws LocalizedException */ - public function testSetShippingMethods():void + public function testSetShippingMethods(): void { $methodsArray = [1 => 'flatrate_flatrate', 2 => 'tablerate_bestway']; $addressId = 1; @@ -603,24 +604,20 @@ public function testCreateOrdersWithThrowsException(array $config): void ->willReturn($config['infoBuyRequest']); $quoteItemMock = $this->getQuoteItemMock($config['productType'], $productMock); $quoteAddressItemMock = - $this->getQuoteAddressItemMock($quoteItemMock, $config['productType'], $config['infoBuyRequest']); + $this->getQuoteAddressItemMock( + $quoteItemMock, + $config['productType'], + $config['infoBuyRequest'] + ); list($shippingAddressMock, $billingAddressMock) = $this->getQuoteAddressesMock($quoteAddressItemMock, $config['addressTotal']); - $this->setQuoteMockData($config['paymentProviderCode'], $shippingAddressMock, $billingAddressMock); - $currencyMock = $this->getMockBuilder(Currency::class) - ->disableOriginalConstructor() - ->setMethods([ 'convert' ]) - ->getMock(); - $currencyMock->method('convert') - ->willReturn($config['shippingPrice']); - $storeMock = $this->getMockBuilder(Store::class) - ->disableOriginalConstructor() - ->setMethods(['getBaseCurrency','getCurrentCurrencyCode' ]) - ->getMock(); - $storeMock->method('getBaseCurrency') - ->willReturn($currencyMock); - $storeMock->method('getCurrentCurrencyCode') - ->willReturn($config['currencyCode']); + $this->setQuoteMockData( + $config['paymentProviderCode'], + $shippingAddressMock, + $billingAddressMock + ); + $currencyMock = $this->getCurrencyMock($config['shippingPrice']); + $storeMock = $this->getStoreMock($currencyMock, $config['currencyCode']); $orderAddressMock = $this->createSimpleMock(OrderAddressInterface::class); $orderPaymentMock = $this->createSimpleMock(OrderPaymentInterface::class); $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class) @@ -629,17 +626,12 @@ public function testCreateOrdersWithThrowsException(array $config): void ->getMock(); $orderItemMock->method('getQuoteItemId') ->willReturn($config['quoteItemId']); - $orderMock = $this->getOrderMock($orderAddressMock, $orderPaymentMock, $orderItemMock); - $orderMock->expects($this->once()) - ->method('getStore') - ->willReturn($storeMock); - $orderMock->expects($this->once()) - ->method('setBaseShippingAmount') - ->with($config['shippingPrice'])->willReturnSelf(); - $orderMock->expects($this->once()) - ->method('setShippingAmount') - ->with($config['shippingPrice']) - ->willReturnSelf(); + $orderMock = $this->getOrderMock( + $orderAddressMock, + $orderPaymentMock, + $orderItemMock + ); + $this->getOrderMockData($orderMock, $storeMock, $config['shippingPrice']); $this->orderFactoryMock->expects($this->once()) ->method('create') ->willReturn($orderMock); @@ -658,7 +650,8 @@ public function testCreateOrdersWithThrowsException(array $config): void ->method('convert') ->with($shippingAddressMock) ->willReturn($orderMock); - $this->toOrderAddressMock->expects($this->exactly(2))->method('convert') + $this->toOrderAddressMock->expects($this->exactly(2)) + ->method('convert') ->withConsecutive( [$billingAddressMock, []], [$shippingAddressMock, []] @@ -688,9 +681,57 @@ public function testCreateOrdersWithThrowsException(array $config): void ->method('save') ->with($this->quoteMock); $this->expectExceptionMessage('Quote address for failed order ID "1" not found.'); + $this->model->createOrders(); } + /** + * Return Store Mock. + * + * @param PHPUnit_Framework_MockObject_MockObject $currencyMock + * @param string $currencyCode + * @return PHPUnit_Framework_MockObject_MockObject + */ + private function getStoreMock($currencyMock, string $currencyCode): PHPUnit_Framework_MockObject_MockObject + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getBaseCurrency','getCurrentCurrencyCode' ]) + ->getMock(); + $storeMock->method('getBaseCurrency') + ->willReturn($currencyMock); + $storeMock->method('getCurrentCurrencyCode') + ->willReturn($currencyCode); + + return $storeMock; + } + + /** + * Return Order Mock with data + * + * @param PHPUnit_Framework_MockObject_MockObject $orderMock + * @param PHPUnit_Framework_MockObject_MockObject $storeMock + * @param string $shippingPrice + * @return void + */ + private function getOrderMockData( + PHPUnit_Framework_MockObject_MockObject $orderMock, + PHPUnit_Framework_MockObject_MockObject $storeMock, + string $shippingPrice + ): void { + $orderMock->expects($this->once()) + ->method('getStore') + ->willReturn($storeMock); + $orderMock->expects($this->once()) + ->method('setBaseShippingAmount') + ->with($shippingPrice) + ->willReturnSelf(); + $orderMock->expects($this->once()) + ->method('setShippingAmount') + ->with($shippingPrice) + ->willReturnSelf(); + } + /** * Return Payment Mock. * @@ -898,12 +939,12 @@ private function getOrderMock( * Tests exception for addresses with country id not in the allowed countries list. * * @return void - * @expectedException LocalizedException - * @expectedExceptionMessage Some addresses can't be used due to the configurations for specific countries. * @throws \Exception */ - public function testCreateOrdersCountryNotPresentInAllowedListException():void + public function testCreateOrdersCountryNotPresentInAllowedListException(): void { + $ExceptionMessage = 'Some addresses can\'t be used due to the configurations for specific countries.'; + $abstractMethod = $this->getMockBuilder(AbstractMethod::class) ->disableOriginalConstructor() ->setMethods(['isAvailable']) @@ -935,18 +976,63 @@ public function testCreateOrdersCountryNotPresentInAllowedListException():void ->willReturn($paymentMock); $this->quoteMock->method('getAllShippingAddresses') ->willReturn([$shippingAddressMock]); + $this->expectExceptionMessage($ExceptionMessage); $this->model->createOrders(); } + /** + * Verify validate minimum amount multi address is false. + * + * @return void + */ + public function testValidateMinimumAmountMultiAddressFalse(): void + { + $addressMock = $this->createMock(\Magento\Quote\Model\Quote\Address::class); + $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( + ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(true, false); + + $this->scopeConfigMock->expects($this->exactly(2))->method('getValue')->withConsecutive( + ['sales/minimum_order/amount', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/tax_including', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(100, false); + + $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once())->method('getStoreId')->willReturn(1); + $this->quoteMock->expects($this->once())->method('getAllAddresses')->willReturn([$addressMock]); + $addressMock->expects($this->once())->method('getBaseSubtotalWithDiscount')->willReturn(101); + + $this->assertTrue($this->model->validateMinimumAmount()); + } + + /** + * Verify validate minimum amount multi address is true. + * + * @return void + */ + public function testValidateMinimumAmountMultiAddressTrue(): void + { + $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( + ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(true, true); + + $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once())->method('validateMinimumAmount')->willReturn(false); + $this->assertFalse($this->model->validateMinimumAmount()); + } + /** * Return Extension Attributes Mock. * * @param ShippingAssignment $shippingAssignmentMock * @return CartExtension|PHPUnit_Framework_MockObject_MockObject */ - private function getExtensionAttributesMock(ShippingAssignment $shippingAssignmentMock) - { + private function getExtensionAttributesMock( + ShippingAssignment $shippingAssignmentMock + ): PHPUnit_Framework_MockObject_MockObject { $extensionAttributesMock = $this->getMockBuilder(CartExtension::class) ->setMethods(['setShippingAssignments']) ->getMock(); @@ -965,7 +1051,7 @@ private function getExtensionAttributesMock(ShippingAssignment $shippingAssignme * * @return ShippingAssignment | PHPUnit_Framework_MockObject_MockObject */ - private function getShippingAssignmentMock() + private function getShippingAssignmentMock(): PHPUnit_Framework_MockObject_MockObject { $shippingAssignmentMock = $this->getMockBuilder(ShippingAssignment::class) ->disableOriginalConstructor() @@ -988,7 +1074,7 @@ private function getShippingAssignmentMock() * * @return void */ - private function mockShippingAssignment():void + private function mockShippingAssignment(): void { $shippingAssignmentMock = $this->getShippingAssignmentMock(); @@ -1017,7 +1103,7 @@ private function mockShippingAssignment():void * @param $customerAddressId * @return Address | PHPUnit_Framework_MockObject_MockObject */ - private function getCustomerAddressMock($customerAddressId) + private function getCustomerAddressMock($customerAddressId): PHPUnit_Framework_MockObject_MockObject { $customerAddressMock = $this->getMockBuilder(Address::class) ->setMethods(['getId']) @@ -1036,7 +1122,7 @@ private function getCustomerAddressMock($customerAddressId) * @param string $className * @return PHPUnit_Framework_MockObject_MockObject */ - private function createSimpleMock($className) + private function createSimpleMock($className): PHPUnit_Framework_MockObject_MockObject { return $this->getMockBuilder($className) ->disableOriginalConstructor() @@ -1044,46 +1130,19 @@ private function createSimpleMock($className) } /** - * Verify validate minimum amount multi address is true. - * - * @return void - */ - public function testValidateMinimumAmountMultiAddressTrue():void - { - $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( - ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(true, true); - - $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); - $this->quoteMock->expects($this->once())->method('validateMinimumAmount')->willReturn(false); - $this->assertFalse($this->model->validateMinimumAmount()); - } - - /** - * Verify validate minimum amount multi address is false. + * Return Currency Mock. * - * @return void + * @param $shippingPrice + * @return PHPUnit_Framework_MockObject_MockObject */ - public function testValidateMinimumAmountMultiAddressFalse():void + private function getCurrencyMock($shippingPrice): PHPUnit_Framework_MockObject_MockObject { - $addressMock = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( - ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(true, false); - - $this->scopeConfigMock->expects($this->exactly(2))->method('getValue')->withConsecutive( - ['sales/minimum_order/amount', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/tax_including', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(100, false); - - $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); - $this->quoteMock->expects($this->once())->method('getStoreId')->willReturn(1); - $this->quoteMock->expects($this->once())->method('getAllAddresses')->willReturn([$addressMock]); - $addressMock->expects($this->once())->method('getBaseSubtotalWithDiscount')->willReturn(101); - - $this->assertTrue($this->model->validateMinimumAmount()); + $currencyMock = $this->getMockBuilder(Currency::class) + ->disableOriginalConstructor() + ->setMethods([ 'convert' ]) + ->getMock(); + $currencyMock->method('convert')->willReturn($shippingPrice); + return $currencyMock; } /** From dec897285bb89e971c9597746d501bf9e84515f6 Mon Sep 17 00:00:00 2001 From: Deepak S Nair Date: Mon, 27 Jan 2020 19:25:14 +0530 Subject: [PATCH 303/666] fix-25761 : resolved static test issues and added translation --- app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php | 5 ++++- .../Sitemap/Model/ItemProvider/StoreUrlConfigReader.php | 3 +++ .../Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php | 2 +- app/code/Magento/Sitemap/i18n/en_US.csv | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php index e262f56d0905f..11a2d585d8da6 100644 --- a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrl.php @@ -8,6 +8,9 @@ use Magento\Sitemap\Model\SitemapItemInterfaceFactory; +/** + * Class for adding Store Url in sitemap + */ class StoreUrl implements ItemProviderInterface { /** @@ -39,7 +42,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getItems($storeId) { diff --git a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php index 782863e79ea4d..b18dd73fb2836 100644 --- a/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php +++ b/app/code/Magento/Sitemap/Model/ItemProvider/StoreUrlConfigReader.php @@ -9,6 +9,9 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface; +/** + * Class for getting configuration for Store Url + */ class StoreUrlConfigReader implements ConfigReaderInterface { /**#@+ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php index e18a54889a1b2..0edfd253f0c1d 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/ItemProvider/StoreUrlTest.php @@ -69,4 +69,4 @@ private function getConfigReaderMock() return $configReaderMock; } -} \ No newline at end of file +} diff --git a/app/code/Magento/Sitemap/i18n/en_US.csv b/app/code/Magento/Sitemap/i18n/en_US.csv index 29ecd7e22773e..8a7ac86e2fb47 100644 --- a/app/code/Magento/Sitemap/i18n/en_US.csv +++ b/app/code/Magento/Sitemap/i18n/en_US.csv @@ -64,3 +64,4 @@ ID,ID "Link for Google","Link for Google" "Last Generated","Last Generated" Action,Action +"Store Url Options","Store Url Options" From 6aeb8653333b0ec8ca926ac81a73b39e17b78467 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko Date: Mon, 27 Jan 2020 15:42:34 +0000 Subject: [PATCH 304/666] magento/magento2#25991: Reverted unnecessary changes --- .../Ui/view/base/web/js/grid/columns/image-preview.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) 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 5dd2b53ec54c6..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 @@ -13,8 +13,6 @@ define([ defaults: { bodyTmpl: 'ui/grid/columns/image-preview', previewImageSelector: '[data-image-preview]', - masonrySelector: '.masonry-image-grid', - isListenerActive: false, visibleRecord: null, height: 0, displayedRecord: {}, @@ -48,6 +46,7 @@ define([ */ initialize: function () { this._super(); + $(document).on('keydown', this.handleKeyDown.bind(this)); return this; }, @@ -131,11 +130,6 @@ define([ show: function (record) { var img; - if (!this.isListenerActive) { - $(this.masonrySelector).on('keydown', this.handleKeyDown.bind(this)); - this.isListenerActive = true; - } - if (record._rowIndex === this.visibleRecord()) { this.hide(); From 83e60706166470c8e8f433670875f67ac7eb810a Mon Sep 17 00:00:00 2001 From: Michele Fantetti Date: Mon, 27 Jan 2020 17:16:49 +0100 Subject: [PATCH 305/666] Add frontend template hints status command unit tests after suggestions --- .../Command/TemplateHintsStatusCommandTest.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php index 27f41a61f9202..7c6ab356b4ada 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Developer\Test\Unit\Console\Command; @@ -33,6 +34,9 @@ class TemplateHintsStatusCommandTest extends TestCase */ private $reinitableConfigMock; + /** + * TemplateHintsStatusCommandTest setup + */ protected function setUp() { $this->scopeConfigMock = $this->getMockForAbstractClass(ScopeConfigInterface::class); @@ -45,16 +49,14 @@ protected function setUp() } + /** + * Test execution + */ public function testExecute() { $tester = new CommandTester($this->command); $tester->execute([]); - $this->assertContains( - 'disabled', - $tester->getDisplay() - ); - $this->assertEquals( 0, $tester->getStatusCode() From 95e9c5e03bdbe86f233ccd7fe522ae9fc88f181a Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko Date: Mon, 27 Jan 2020 13:51:34 -0600 Subject: [PATCH 306/666] MC-25265: Pagebuilder products list doesn't work with anchor category --- .../Catalog/Model/ResourceModel/Product/Collection.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index e31180d4ff6cf..afbe279045a38 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -2121,7 +2121,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]; } } From 9f6fcbb3ab0394322a247f6a5f412d494b4b4e49 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal Date: Mon, 27 Jan 2020 21:51:52 +0200 Subject: [PATCH 307/666] Improved code readability --- .../Block/Tracking/PopupDeliveryDateTest.php | 91 +++++++++++++------ 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php index a5cd261ab7121..80cd37c3bde5e 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -21,16 +21,36 @@ */ class PopupDeliveryDateTest extends TestCase { + const STUB_CARRIER_CODE_NOT_FEDEX = 'not-fedex'; + const STUB_DELIVERY_DATE = '2020-02-02'; + const STUB_DELIVERY_TIME = '12:00'; + /** * @var MockObject|PopupDeliveryDate */ private $plugin; + /** + * @var MockObject|Status $trackingStatusMock + */ + private $trackingStatusMock; + + /** + * @var MockObject|Popup $subjectMock + */ + private $subjectMock; + /** * @inheritDoc */ protected function setUp() { + $this->trackingStatusMock = $this->getStatusMock(); + $this->subjectMock = $this->getPopupMock(); + $this->subjectMock->expects($this->once()) + ->method('getTrackingInfo') + ->willReturn([[$this->trackingStatusMock]]); + $objectManagerHelper = new ObjectManager($this); $this->plugin = $objectManagerHelper->getObject(PopupDeliveryDate::class); } @@ -40,27 +60,14 @@ protected function setUp() */ public function testAfterFormatDeliveryDateTimeWithFedexCarrier() { - /** @var Status|MockObject $trackingStatusMock */ - $trackingStatusMock = $this->getMockBuilder(Status::class) - ->disableOriginalConstructor() - ->setMethods(['getCarrier']) - ->getMock(); - $trackingStatusMock->expects($this::once()) + $this->trackingStatusMock->expects($this::once()) ->method('getCarrier') ->willReturn(Carrier::CODE); - /** @var Popup|MockObject $subjectMock */ - $subjectMock = $this->getMockBuilder(Popup::class) - ->disableOriginalConstructor() - ->setMethods(['formatDeliveryDate', 'getTrackingInfo']) - ->getMock(); - $subjectMock->expects($this->once()) - ->method('getTrackingInfo') - ->willReturn([[$trackingStatusMock]]); - $subjectMock->expects($this->once()) + $this->subjectMock->expects($this->once()) ->method('formatDeliveryDate'); - $this->plugin->afterFormatDeliveryDateTime($subjectMock, 'Test Result', '2020-02-02', '12:00'); + $this->executeOriginalMethod(); } /** @@ -68,26 +75,52 @@ public function testAfterFormatDeliveryDateTimeWithFedexCarrier() */ public function testAfterFormatDeliveryDateTimeWithOtherCarrier() { - /** @var Status|MockObject $trackingStatusMock */ - $trackingStatusMock = $this->getMockBuilder(Status::class) + $this->trackingStatusMock->expects($this::once()) + ->method('getCarrier') + ->willReturn(self::STUB_CARRIER_CODE_NOT_FEDEX); + + $this->subjectMock->expects($this->never()) + ->method('formatDeliveryDate'); + + $this->executeOriginalMethod(); + } + + /** + * Returns Mock for @see Status + * + * @return MockObject + */ + private function getStatusMock(): MockObject + { + return $this->getMockBuilder(Status::class) ->disableOriginalConstructor() ->setMethods(['getCarrier']) ->getMock(); - $trackingStatusMock->expects($this::once()) - ->method('getCarrier') - ->willReturn('not-fedex'); + } - /** @var Popup|MockObject $subjectMock */ - $subjectMock = $this->getMockBuilder(Popup::class) + /** + * Returns Mock for @see Popup + * + * @return MockObject + */ + private function getPopupMock(): MockObject + { + return $this->getMockBuilder(Popup::class) ->disableOriginalConstructor() ->setMethods(['formatDeliveryDate', 'getTrackingInfo']) ->getMock(); - $subjectMock->expects($this->once()) - ->method('getTrackingInfo') - ->willReturn([[$trackingStatusMock]]); - $subjectMock->expects($this->never()) - ->method('formatDeliveryDate'); + } - $this->plugin->afterFormatDeliveryDateTime($subjectMock, 'Test Result', '2020-02-02', '12:00'); + /** + * + */ + private function executeOriginalMethod() + { + $this->plugin->afterFormatDeliveryDateTime( + $this->subjectMock, + 'Test Result', + self::STUB_DELIVERY_DATE, + self::STUB_DELIVERY_TIME + ); } } From cdc0834c23c97fd6d052e7a99f8456dc4193a016 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal Date: Mon, 27 Jan 2020 21:55:05 +0200 Subject: [PATCH 308/666] Comment added --- .../Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php index 80cd37c3bde5e..109f6199b52c6 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -112,7 +112,7 @@ private function getPopupMock(): MockObject } /** - * + * Run plugin's original method */ private function executeOriginalMethod() { From 5342a25c5df6a8652b25b688935d20fd1b8e2d6c Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal Date: Mon, 27 Jan 2020 22:38:44 +0200 Subject: [PATCH 309/666] Constants added --- .../Test/Unit/Observer/EventSaverTest.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php index eebed5bfc0431..07e9eef40f4de 100644 --- a/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php +++ b/app/code/Magento/Reports/Test/Unit/Observer/EventSaverTest.php @@ -24,6 +24,12 @@ */ class EventSaverTest extends TestCase { + const STUB_CUSTOMER_ID = 1; + const STUB_VISITOR_ID = 2; + const STUB_EVENT_TYPE_ID = 1; + const STUB_OBJECT_ID = 1; + const STUB_STORE_ID = 1; + /** * @var Session|MockObject */ @@ -74,7 +80,7 @@ public function setUp() ->willReturn($this->storeMock); $this->storeMock->expects($this->once()) ->method('getId') - ->willReturn(1); + ->willReturn(self::STUB_STORE_ID); $this->eventMock = $this->createMock(Event::class); $this->eventFactoryMock = $this->createMock(EventFactory::class); @@ -112,7 +118,7 @@ public function testSaveWithSubject() ->method('getCustomerId'); $this->customerVisitorMock->expects($this->never()) ->method('getId'); - $this->eventSaver->save(1, 1, $subjectId); + $this->eventSaver->save(self::STUB_EVENT_TYPE_ID, self::STUB_OBJECT_ID, $subjectId); } /** @@ -125,8 +131,8 @@ public function testSaveWithoutSubjectWhenLoggedIn() ->willReturn(true); $this->customerSessionMock->expects($this->once()) ->method('getCustomerId') - ->willReturn(1); - $this->eventSaver->save(1, 1, null); + ->willReturn(self::STUB_CUSTOMER_ID); + $this->eventSaver->save(self::STUB_EVENT_TYPE_ID, self::STUB_OBJECT_ID, null); } /** @@ -139,7 +145,7 @@ public function testSaveWithoutSubjectForGuest() ->willReturn(false); $this->customerVisitorMock->expects($this->once()) ->method('getId') - ->willReturn(2); - $this->eventSaver->save(1, 1, null); + ->willReturn(self::STUB_VISITOR_ID); + $this->eventSaver->save(self::STUB_EVENT_TYPE_ID, self::STUB_OBJECT_ID, null); } } From ece031d464e611a7b1567ccf6b9f452e2bb6e432 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Tue, 28 Jan 2020 09:00:57 +0200 Subject: [PATCH 310/666] Covering the model classes by Unit Tests --- .../Unit/Model/Mode/ConfigManagerTest.php | 109 ++++++++++++++++++ .../Unit/Model/PolicyRendererPoolTest.php | 96 +++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php create mode 100644 app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php new file mode 100644 index 0000000000000..2bc23a520cd71 --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -0,0 +1,109 @@ +scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + $this->storeMock = $this->createMock(Store::class); + $this->stateMock = $this->createMock(State::class); + + $this->model = $objectManager->getObject( + ConfigManager::class, + [ + 'config' => $this->scopeConfigMock, + 'storeModel' => $this->storeMock, + 'state' => $this->stateMock + ] + ); + } + + /** + * Test throwing an exception for non storefront or admin areas + * + * @return void + * + * @expectedExceptionMessage CSP can only be configured for storefront or admin area + * @expectedException RuntimeException + */ + public function testThrownExceptionForCrontabArea() + { + $this->stateMock->expects($this->any()) + ->method('getAreaCode') + ->willReturn(static::STUB_CRONTAB_AREA); + + $this->model->getConfigured(); + } + + /** + * Test returning the configured CSP for admin area + * + * @return void + */ + public function testConfiguredCSPForAdminArea() + { + $this->stateMock->expects($this->any()) + ->method('getAreaCode') + ->willReturn(Area::AREA_ADMINHTML); + $this->scopeConfigMock->expects($this->any()) + ->method('isSetFlag') + ->willReturn(true); + $this->scopeConfigMock->expects($this->any()) + ->method('getValue') + ->willReturn('testReportUri'); + $result = $this->model->getConfigured(); + + $this->assertInstanceOf(ModeConfigured::class, $result); + } +} diff --git a/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php new file mode 100644 index 0000000000000..1bc98a5232d04 --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php @@ -0,0 +1,96 @@ +simplePolicyHeaderRendererMock = $this->createPartialMock( + SimplePolicyHeaderRenderer::class, + ['canRender'] + ); + $this->policyMock = $this->createMock(PolicyInterface::class); + + $this->model = $objectManager->getObject( + PolicyRendererPool::class, + [ + 'renderers' => [ + $this->simplePolicyHeaderRendererMock + ] + ] + ); + } + + /** + * Test throwing an exception for not found policy renders + * + * @return void + * + * @expectedExceptionMessage Failed to find a renderer for policy + * @expectedException RuntimeException + */ + public function testThrownExceptionForNotFoundPolicyRenders() + { + $this->policyMock->expects($this->any()) + ->method('getId') + ->willReturn(static::STUB_POLICY_ID); + + $this->model->getRenderer($this->policyMock); + } + + /** + * Test returning a renderer for the given policy + * + * @return void + */ + public function testReturningThePolicyRender() + { + $this->simplePolicyHeaderRendererMock->expects($this->any()) + ->method('canRender') + ->with($this->policyMock) + ->willReturn(true); + + $this->model->getRenderer($this->policyMock); + } +} From 7811896f1740f72fa6ae825c308e39a16c948abf Mon Sep 17 00:00:00 2001 From: eduard13 Date: Tue, 28 Jan 2020 09:14:14 +0200 Subject: [PATCH 311/666] Covering the model classes by Unit Tests --- .../Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php | 4 +--- .../Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php index 2bc23a520cd71..adab15eacd6dc 100644 --- a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -26,8 +26,6 @@ */ class ConfigManagerTest extends TestCase { - const STUB_CRONTAB_AREA = 'crontab'; - /** * @var ConfigManager */ @@ -81,7 +79,7 @@ public function testThrownExceptionForCrontabArea() { $this->stateMock->expects($this->any()) ->method('getAreaCode') - ->willReturn(static::STUB_CRONTAB_AREA); + ->willReturn(Area::AREA_CRONTAB); $this->model->getConfigured(); } diff --git a/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php index 1bc98a5232d04..2b551d4b8dcaf 100644 --- a/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php +++ b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php @@ -23,7 +23,7 @@ */ class PolicyRendererPoolTest extends TestCase { - const STUB_POLICY_ID = 'header'; + private const STUB_POLICY_ID = 'header'; /** * @var PolicyRendererPool From 988309d6d0ad534846e37b5cb264e0ea51794679 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Tue, 28 Jan 2020 09:27:03 +0200 Subject: [PATCH 312/666] Covering the model classes by Unit Tests --- app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php index adab15eacd6dc..c574abc1bad59 100644 --- a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace Magento\Csp\Test\Unit\Model; +namespace Magento\Csp\Test\Unit\Model\Mode; use Magento\Csp\Model\Mode\ConfigManager; use Magento\Csp\Model\Mode\Data\ModeConfigured; From 6fbdbbed12051bc306174e1f4f828c3e00ac2e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chitesh=40wagento=2Ecom=E2=80=9D?= Date: Tue, 28 Jan 2020 13:08:36 +0530 Subject: [PATCH 313/666] [Applied changes as per suggession] --- .../web/css/source/_module.less | 19 ++++++++----------- .../web/css/source/_module.less | 19 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less index b26abd2731131..20a026ac2af9c 100644 --- a/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Wishlist/web/css/source/_module.less @@ -53,17 +53,6 @@ } } - .products-grid.wishlist { - .product-item { - margin-left: 2%; - padding: 5px; - width: calc(~'(100% - 4%) / 3'); - &:nth-child(3n + 1) { - margin-left: 0; - } - } - } - .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -139,6 +128,13 @@ .products-grid.wishlist { .product { &-item { + margin-left: 2%; + width: calc(~'(100% - 4%) / 3'); + + &:nth-child(3n + 1) { + margin-left: 0; + } + &-photo { display: block; margin-bottom: @indent__s; @@ -198,6 +194,7 @@ border-bottom: 1px solid @secondary__color; margin: 0; width: 100%; + &:first-child { border-top: 1px solid @secondary__color; } diff --git a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less index 0c4be4dcd6c00..69342821e9b17 100644 --- a/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Wishlist/web/css/source/_module.less @@ -45,17 +45,6 @@ } } - .products-grid.wishlist { - .product-item { - margin-left: 2%; - padding: 5px; - width: calc(~'(100% - 4%) / 3'); - &:nth-child(3n + 1) { - margin-left: 0; - } - } - } - .account .table-wrapper .data.table.wishlist { .lib-table-bordered( @_table_type: horizontal @@ -146,6 +135,13 @@ .products-grid.wishlist { .product { &-item { + margin-left: 2%; + width: calc(~'(100% - 4%) / 3'); + + &:nth-child(3n + 1) { + margin-left: 0; + } + &-photo { display: block; margin-bottom: @indent__s; @@ -229,6 +225,7 @@ border-bottom: 1px solid @secondary__color; margin: 0; width: 100%; + &:first-child { border-top: 1px solid @secondary__color; } From 52a5fb621acc981fa56d592c9d6ccf7254174ceb Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" Date: Tue, 28 Jan 2020 11:03:28 +0200 Subject: [PATCH 314/666] MC-29579: After MC-22931 shipping price displays without tax --- app/code/Magento/Customer/etc/fieldset.xml | 17 -- .../Quote/Model/ShippingMethodManagement.php | 39 +++- .../_files/customer_group_rollback.php | 30 ++++ .../Model/ShippingMethodManagementTest.php | 167 +++++++++++++++++- .../Magento/Tax/_files/tax_classes_de.php | 58 ++++++ .../Tax/_files/tax_classes_de_rollback.php | 64 +++++++ 6 files changed, 348 insertions(+), 27 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_group_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de.php create mode 100644 dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de_rollback.php diff --git a/app/code/Magento/Customer/etc/fieldset.xml b/app/code/Magento/Customer/etc/fieldset.xml index f89b653981520..ebd0fb2e57efe 100644 --- a/app/code/Magento/Customer/etc/fieldset.xml +++ b/app/code/Magento/Customer/etc/fieldset.xml @@ -57,23 +57,6 @@ -
- - - - - - - - - - - - - - - -
diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php index f62866539c6cc..73a2a43b2581f 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php @@ -7,6 +7,7 @@ namespace Magento\Quote\Model; use Magento\Customer\Api\Data\AddressInterfaceFactory; +use Magento\Customer\Model\Session as CustomerSession; use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\InputException; @@ -22,6 +23,7 @@ * Shipping method read service * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class ShippingMethodManagement implements \Magento\Quote\Api\ShippingMethodManagementInterface, @@ -69,6 +71,11 @@ class ShippingMethodManagement implements */ private $quoteAddressResource; + /** + * @var CustomerSession + */ + private $customerSession; + /** * Constructor * @@ -78,6 +85,7 @@ class ShippingMethodManagement implements * @param Quote\TotalsCollector $totalsCollector * @param AddressInterfaceFactory|null $addressFactory * @param QuoteAddressResource|null $quoteAddressResource + * @param CustomerSession|null $customerSession */ public function __construct( \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, @@ -85,7 +93,8 @@ public function __construct( \Magento\Customer\Api\AddressRepositoryInterface $addressRepository, \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector, AddressInterfaceFactory $addressFactory = null, - QuoteAddressResource $quoteAddressResource = null + QuoteAddressResource $quoteAddressResource = null, + CustomerSession $customerSession = null ) { $this->quoteRepository = $quoteRepository; $this->converter = $converter; @@ -95,10 +104,11 @@ public function __construct( ->get(AddressInterfaceFactory::class); $this->quoteAddressResource = $quoteAddressResource ?: ObjectManager::getInstance() ->get(QuoteAddressResource::class); + $this->customerSession = $customerSession ?? ObjectManager::getInstance()->get(CustomerSession::class); } /** - * {@inheritDoc} + * @inheritDoc */ public function get($cartId) { @@ -126,7 +136,7 @@ public function get($cartId) } /** - * {@inheritDoc} + * @inheritDoc */ public function getList($cartId) { @@ -155,7 +165,7 @@ public function getList($cartId) } /** - * {@inheritDoc} + * @inheritDoc */ public function set($cartId, $carrierCode, $methodCode) { @@ -176,6 +186,8 @@ public function set($cartId, $carrierCode, $methodCode) } /** + * Apply carrier code. + * * @param int $cartId The shopping cart ID. * @param string $carrierCode The carrier code. * @param string $methodCode The shipping method code. @@ -209,7 +221,7 @@ public function apply($cartId, $carrierCode, $methodCode) } /** - * {@inheritDoc} + * @inheritDoc */ public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address) { @@ -240,7 +252,7 @@ public function estimateByExtendedAddress($cartId, AddressInterface $address) } /** - * {@inheritDoc} + * @inheritDoc */ public function estimateByAddressId($cartId, $addressId) { @@ -266,6 +278,7 @@ public function estimateByAddressId($cartId, $addressId) * @param string $region * @param \Magento\Framework\Api\ExtensibleDataInterface|null $address * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods. + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @deprecated 100.2.0 */ protected function getEstimatedRates( @@ -277,11 +290,10 @@ protected function getEstimatedRates( $address = null ) { if (!$address) { - $address = $this->getAddressFactory()->create() + $address = $this->addressFactory->create() ->setCountryId($country) ->setPostcode($postcode) - ->setRegionId($regionId) - ->setRegion($region); + ->setRegionId($regionId); } return $this->getShippingMethods($quote, $address); } @@ -301,12 +313,21 @@ private function getShippingMethods(Quote $quote, $address) $shippingAddress->setCollectShippingRates(true); $this->totalsCollector->collectAddressTotals($quote, $shippingAddress); + $quoteCustomerGroupId = $quote->getCustomerGroupId(); + $customerGroupId = $this->customerSession->getCustomerGroupId(); + $isCustomerGroupChanged = $quoteCustomerGroupId !== $customerGroupId; + if ($isCustomerGroupChanged) { + $quote->setCustomerGroupId($customerGroupId); + } $shippingRates = $shippingAddress->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { $output[] = $this->converter->modelToDataObject($rate, $quote->getQuoteCurrencyCode()); } } + if ($isCustomerGroupChanged) { + $quote->setCustomerGroupId($quoteCustomerGroupId); + } return $output; } diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_group_rollback.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_group_rollback.php new file mode 100644 index 0000000000000..20a1f4623a1f7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_group_rollback.php @@ -0,0 +1,30 @@ +get(GroupRepositoryInterface::class); +/** @var SearchCriteriaBuilder $searchBuilder */ +$searchBuilder = $objectManager->get(SearchCriteriaBuilder::class); +$searchCriteria = $searchBuilder->addFilter(GroupInterface::CODE, 'custom_group') + ->create(); +$groups = $groupRepository->getList($searchCriteria) + ->getItems(); +foreach ($groups as $group) { + try { + $groupRepository->delete($group); + } catch (NoSuchEntityException $exception) { + //Group already removed + } +} diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php index 8db7b65d0142d..1a4e640a1eabe 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php @@ -6,13 +6,52 @@ 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\Framework\Api\SearchCriteriaBuilder; +use Magento\Tax\Api\TaxClassRepositoryInterface; +use Magento\Tax\Api\Data\TaxClassInterface; + /** - * Class ShippingMethodManagementTest + * Test for shipping methods management * * @magentoDbIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShippingMethodManagementTest extends \PHPUnit\Framework\TestCase { + /** @var ObjectManagerInterface $objectManager */ + private $objectManager; + + /** @var GroupRepositoryInterface $groupRepository */ + private $groupRepository; + + /** @var TaxClassRepositoryInterface $taxClassRepository */ + private $taxClassRepository; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->groupRepository = $this->objectManager->get(GroupRepositoryInterface::class); + $this->taxClassRepository = $this->objectManager->get(TaxClassRepositoryInterface::class); + } + /** * @magentoDataFixture Magento/SalesRule/_files/cart_rule_100_percent_off.php * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php @@ -173,4 +212,130 @@ private function executeTestFlow($flatRateAmount, $tableRateAmount) $this->assertEquals($expectedResult[$rate->getCarrierCode()]['method_code'], $rate->getMethodCode()); } } + + /** + * Test for estimate shipping with tax and changed VAT customer group + * + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/Tax/_files/tax_classes_de.php + * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php + * @magentoDataFixture Magento/Customer/_files/customer_group.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * @magentoConfigFixture current_store customer/create_account/tax_calculation_address_type shipping + * @magentoConfigFixture current_store customer/create_account/default_group 1 + * @magentoConfigFixture current_store customer/create_account/auto_group_assign 1 + * @magentoConfigFixture current_store tax/calculation/price_includes_tax 1 + * @magentoConfigFixture current_store tax/calculation/shipping_includes_tax 1 + */ + public function testEstimateByAddressWithInclExclTaxAndVATGroup() + { + /** @var CustomerRepositoryInterface $customerRepository */ + $customerRepository = $this->objectManager->get(CustomerRepositoryInterface::class); + $customer = $customerRepository->get('customer@example.com'); + + /** @var GroupInterface $customerGroup */ + $customerGroup = $this->findCustomerGroupByCode('custom_group'); + $customerGroup->setTaxClassId($this->getTaxClass('CustomerTaxClass')->getClassId()); + $this->groupRepository->save($customerGroup); + + $customer->setGroupId($customerGroup->getId()); + $customer->setTaxvat('12'); + $customerRepository->save($customer); + $this->setConfig($customerGroup->getId(), $this->getTaxClass('ProductTaxClass')->getClassId()); + $this->changeCustomerAddress($customer->getDefaultShipping()); + + $quote = $this->objectManager->get(GetQuoteByReservedOrderId::class)->execute('test01'); + + /** @var ShippingMethodManagementInterface $shippingEstimation */ + $shippingEstimation = $this->objectManager->get(ShippingMethodManagementInterface::class); + $result = $shippingEstimation->estimateByAddressId($quote->getId(), $customer->getDefaultShipping()); + + $this->assertEquals(6.05, $result[0]->getPriceInclTax()); + $this->assertEquals(5.0, $result[0]->getPriceExclTax()); + } + + /** + * Find the group with a given code. + * + * @param string $code + * + * @return GroupInterface + */ + protected function findCustomerGroupByCode(string $code): ?GroupInterface + { + /** @var SearchCriteriaBuilder $searchBuilder */ + $searchBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchBuilder->addFilter('code', $code) + ->create(); + $groups = $this->groupRepository->getList($searchCriteria) + ->getItems(); + + return array_shift($groups); + } + + /** + * Change customer address + * + * @param int $customerAddressId + * + * @return AddressInterface + */ + private function changeCustomerAddress(int $customerAddressId): AddressInterface + { + $addressRepository = $this->objectManager->get(AddressRepositoryInterface::class); + $address = $addressRepository->getById($customerAddressId); + $address->setVatId(12345); + $address->setCountryId('DE'); + $address->setRegionId(0); + $address->setPostcode(10178); + + return $addressRepository->save($address); + } + + /** + * Get tax class. + * + * @param string $name + * + * @return TaxClassInterface + */ + private function getTaxClass(string $name): ?TaxClassInterface + { + /** @var SearchCriteriaBuilder $searchBuilder */ + $searchBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchBuilder->addFilter(ClassModel::KEY_NAME, $name) + ->create(); + $searchResults = $this->taxClassRepository->getList($searchCriteria) + ->getItems(); + + return array_shift($searchResults); + } + + /** + * Set the configuration. + * + * @param int $customerGroupId + * @param int $productTaxClassId + * + * @return void + */ + private function setConfig(int $customerGroupId, int $productTaxClassId): void + { + $configData = [ + [ + 'path' => Vat::XML_PATH_CUSTOMER_VIV_INVALID_GROUP, + 'value' => $customerGroupId, + 'scope' => ScopeInterface::SCOPE_STORE, + ], + [ + 'path' => TaxConfig::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, + 'value' => $productTaxClassId, + 'scope' => ScopeInterface::SCOPE_STORE, + ], + ]; + $config = $this->objectManager->get(MutableScopeConfigInterface::class); + foreach ($configData as $data) { + $config->setValue($data['path'], $data['value'], $data['scope']); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de.php new file mode 100644 index 0000000000000..d2115e4488b14 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de.php @@ -0,0 +1,58 @@ +get(TaxClassRepositoryInterface::class); +$taxClassFactory = $objectManager->get(TaxClassInterfaceFactory::class); +/** @var TaxClassInterface $taxClassDataObject */ +$taxClassDataObject = $taxClassFactory->create(); +$taxClassDataObject->setClassName('CustomerTaxClass') + ->setClassType(TaxClassManagementInterface::TYPE_CUSTOMER); +$taxCustomerClassId = $taxClassRepository->save($taxClassDataObject); +$taxClassDataObject = $taxClassFactory->create(); +$taxClassDataObject->setClassName('ProductTaxClass') + ->setClassType(TaxClassManagementInterface::TYPE_PRODUCT); +$taxProductClassId = $taxClassRepository->save($taxClassDataObject); + +$taxRateFactory = $objectManager->get(TaxRateInterfaceFactory::class); +/** @var TaxRateInterface $taxRate */ +$taxRate = $taxRateFactory->create(); +$taxRate->setTaxCountryId('DE') + ->setTaxRegionId(0) + ->setTaxPostcode('*') + ->setCode('Denmark') + ->setRate('21'); +/** @var TaxRateRepositoryInterface $taxRateRepository */ +$taxRateRepository = $objectManager->get(TaxRateRepositoryInterface::class); +$taxRate = $taxRateRepository->save($taxRate); + +/** @var TaxRuleRepositoryInterface $taxRuleRepository */ +$taxRuleRepository = $objectManager->get(TaxRuleRepositoryInterface::class); +$taxRuleFactory = $objectManager->get(TaxRuleInterfaceFactory::class); +/** @var TaxRuleInterface $taxRule */ +$taxRule = $taxRuleFactory->create(); +$taxRule->setCode('Test Rule') + ->setCustomerTaxClassIds([$taxCustomerClassId]) + ->setProductTaxClassIds([$taxProductClassId]) + ->setTaxRateIds([$taxRate->getId()]) + ->setPriority(0); +$taxRuleRepository->save($taxRule); diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de_rollback.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de_rollback.php new file mode 100644 index 0000000000000..a87a031ee78a6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_classes_de_rollback.php @@ -0,0 +1,64 @@ +get(TaxRuleRepositoryInterface::class); +/** @var SearchCriteriaBuilder $searchBuilder */ +$searchBuilder = $objectManager->get(SearchCriteriaBuilder::class); +$searchCriteria = $searchBuilder->addFilter(Rule::KEY_CODE, 'Test Rule') + ->create(); +$taxRules = $taxRuleRepository->getList($searchCriteria) + ->getItems(); +foreach ($taxRules as $taxRule) { + try { + $taxRuleRepository->delete($taxRule); + } catch (NoSuchEntityException $exception) { + //Rule already removed + } +} +$searchCriteria = $searchBuilder->addFilter(ClassModel::KEY_NAME, $taxClasses, 'in') + ->create(); +/** @var TaxClassRepositoryInterface $groupRepository */ +$taxClassRepository = $objectManager->get(TaxClassRepositoryInterface::class); +$taxClasses = $taxClassRepository->getList($searchCriteria) + ->getItems(); +foreach ($taxClasses as $taxClass) { + try { + $taxClassRepository->delete($taxClass); + } catch (NoSuchEntityException $exception) { + //TaxClass already removed + } +} +$searchCriteria = $searchBuilder->addFilter(Rate::KEY_CODE, 'Denmark') + ->create(); +/** @var TaxRateRepositoryInterface $groupRepository */ +$taxRateRepository = $objectManager->get(TaxRateRepositoryInterface::class); +$taxRates = $taxRateRepository->getList($searchCriteria) + ->getItems(); +foreach ($taxRates as $taxRate) { + try { + $taxRateRepository->delete($taxRate); + } catch (NoSuchEntityException $exception) { + //TaxRate already removed + } +} From 539c087563155416e6508cc763de9bf7df9aa42f Mon Sep 17 00:00:00 2001 From: Nazar Klovanych Date: Tue, 28 Jan 2020 11:06:32 +0200 Subject: [PATCH 315/666] Refactor Multishipping test for standarts --- .../Model/Checkout/Type/MultishippingTest.php | 241 +++++++++--------- 1 file changed, 127 insertions(+), 114 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index 3948025fa0388..397ea8a59e2aa 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -57,7 +57,7 @@ use Magento\Sales\Model\OrderFactory; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Test class Multishipping @@ -73,112 +73,112 @@ class MultishippingTest extends \PHPUnit\Framework\TestCase protected $model; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $checkoutSessionMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $customerSessionMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $customerMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $quoteMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $helperMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $filterBuilderMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $addressRepositoryMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $searchCriteriaBuilderMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ protected $totalsCollectorMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $cartExtensionFactoryMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $shippingAssignmentProcessorMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $quoteRepositoryMock; /** - * @var OrderFactory|PHPUnit_Framework_MockObject_MockObject + * @var OrderFactory|MockObject */ private $orderFactoryMock; /** - * @var \Magento\Framework\Api\DataObjectHelper|PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Api\DataObjectHelper|MockObject */ private $dataObjectHelperMock; /** - * @var ToOrder|PHPUnit_Framework_MockObject_MockObject + * @var ToOrder|MockObject */ private $toOrderMock; /** - * @var ToOrderAddress|PHPUnit_Framework_MockObject_MockObject + * @var ToOrderAddress|MockObject */ private $toOrderAddressMock; /** - * @var ToOrderPayment|PHPUnit_Framework_MockObject_MockObject + * @var ToOrderPayment|MockObject */ private $toOrderPaymentMock; /** - * @var PriceCurrencyInterface|PHPUnit_Framework_MockObject_MockObject + * @var PriceCurrencyInterface|MockObject */ private $priceMock; /** - * @var ToOrderItem|PHPUnit_Framework_MockObject_MockObject + * @var ToOrderItem|MockObject */ private $toOrderItemMock; /** - * @var PlaceOrderFactory|PHPUnit_Framework_MockObject_MockObject + * @var PlaceOrderFactory|MockObject */ private $placeOrderFactoryMock; /** - * @var Generic|PHPUnit_Framework_MockObject_MockObject + * @var Generic|MockObject */ private $sessionMock; /** - * @var PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $scopeConfigMock; @@ -598,19 +598,25 @@ public function testCreateOrdersWithThrowsException(array $config): void ->disableOriginalConstructor() ->setMethods(['getOrderOptions']) ->getMock(); + $orderAddressMock = $this->createSimpleMock(OrderAddressInterface::class); + $orderPaymentMock = $this->createSimpleMock(OrderPaymentInterface::class); + $orderItemMock = $this->createMock(\Magento\Sales\Model\Order\Item::class); $productMock = $this->getProductMock($simpleProductTypeMock); - $simpleProductTypeMock->method('getOrderOptions') - ->with($productMock) - ->willReturn($config['infoBuyRequest']); + $orderMock = $this->getOrderMock( + $orderAddressMock, + $orderPaymentMock, + $orderItemMock + ); $quoteItemMock = $this->getQuoteItemMock($config['productType'], $productMock); - $quoteAddressItemMock = - $this->getQuoteAddressItemMock( - $quoteItemMock, - $config['productType'], - $config['infoBuyRequest'] - ); - list($shippingAddressMock, $billingAddressMock) = - $this->getQuoteAddressesMock($quoteAddressItemMock, $config['addressTotal']); + $quoteAddressItemMock = $this->getQuoteAddressItemMock( + $quoteItemMock, + $config['productType'], + $config['infoBuyRequest'] + ); + list($shippingAddressMock, $billingAddressMock) = $this->getQuoteAddressesMock( + $quoteAddressItemMock, + $config['addressTotal'] + ); $this->setQuoteMockData( $config['paymentProviderCode'], $shippingAddressMock, @@ -618,30 +624,23 @@ public function testCreateOrdersWithThrowsException(array $config): void ); $currencyMock = $this->getCurrencyMock($config['shippingPrice']); $storeMock = $this->getStoreMock($currencyMock, $config['currencyCode']); - $orderAddressMock = $this->createSimpleMock(OrderAddressInterface::class); - $orderPaymentMock = $this->createSimpleMock(OrderPaymentInterface::class); - $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class) + $placeOrderServiceMock = $this->getMockBuilder(PlaceOrderDefault::class) ->disableOriginalConstructor() - ->setMethods(['getQuoteItemId']) + ->setMethods(['place']) ->getMock(); - $orderItemMock->method('getQuoteItemId') - ->willReturn($config['quoteItemId']); - $orderMock = $this->getOrderMock( - $orderAddressMock, - $orderPaymentMock, - $orderItemMock - ); + + $orderItemMock->method('getQuoteItemId')->willReturn($config['quoteItemId']); + $simpleProductTypeMock->method('getOrderOptions') + ->with($productMock) + ->willReturn($config['infoBuyRequest']); $this->getOrderMockData($orderMock, $storeMock, $config['shippingPrice']); $this->orderFactoryMock->expects($this->once()) ->method('create') ->willReturn($orderMock); $this->dataObjectHelperMock->expects($this->once()) ->method('mergeDataObjects') - ->with( - OrderInterface::class, - $orderMock, - $orderMock - )->willReturnSelf(); + ->with(OrderInterface::class, $orderMock, $orderMock) + ->willReturnSelf(); $this->priceMock->expects($this->once()) ->method('round') ->with($config['addressTotal']) @@ -652,19 +651,13 @@ public function testCreateOrdersWithThrowsException(array $config): void ->willReturn($orderMock); $this->toOrderAddressMock->expects($this->exactly(2)) ->method('convert') - ->withConsecutive( - [$billingAddressMock, []], - [$shippingAddressMock, []] - )->willReturn($orderAddressMock); + ->withConsecutive([$billingAddressMock, []], [$shippingAddressMock, []]) + ->willReturn($orderAddressMock); $this->toOrderPaymentMock->method('convert') ->willReturn($orderPaymentMock); $this->toOrderItemMock->method('convert') ->with($quoteAddressItemMock) ->willReturn($orderItemMock); - $placeOrderServiceMock = $this->getMockBuilder(PlaceOrderDefault::class) - ->disableOriginalConstructor() - ->setMethods(['place']) - ->getMock(); $placeOrderServiceMock->method('place') ->with([$orderMock]) ->willReturn([$config['quoteId'] => new \Exception()]); @@ -680,6 +673,7 @@ public function testCreateOrdersWithThrowsException(array $config): void $this->quoteRepositoryMock->expects($this->once()) ->method('save') ->with($this->quoteMock); + $this->expectExceptionMessage('Quote address for failed order ID "1" not found.'); $this->model->createOrders(); @@ -688,11 +682,11 @@ public function testCreateOrdersWithThrowsException(array $config): void /** * Return Store Mock. * - * @param PHPUnit_Framework_MockObject_MockObject $currencyMock + * @param MockObject $currencyMock * @param string $currencyCode - * @return PHPUnit_Framework_MockObject_MockObject + * @return MockObject */ - private function getStoreMock($currencyMock, string $currencyCode): PHPUnit_Framework_MockObject_MockObject + private function getStoreMock($currencyMock, string $currencyCode): MockObject { $storeMock = $this->getMockBuilder(Store::class) ->disableOriginalConstructor() @@ -709,14 +703,14 @@ private function getStoreMock($currencyMock, string $currencyCode): PHPUnit_Fram /** * Return Order Mock with data * - * @param PHPUnit_Framework_MockObject_MockObject $orderMock - * @param PHPUnit_Framework_MockObject_MockObject $storeMock + * @param MockObject $orderMock + * @param MockObject $storeMock * @param string $shippingPrice * @return void */ private function getOrderMockData( - PHPUnit_Framework_MockObject_MockObject $orderMock, - PHPUnit_Framework_MockObject_MockObject $storeMock, + MockObject $orderMock, + MockObject $storeMock, string $shippingPrice ): void { $orderMock->expects($this->once()) @@ -736,9 +730,9 @@ private function getOrderMockData( * Return Payment Mock. * * @param string $paymentProviderCode - * @return PHPUnit_Framework_MockObject_MockObject + * @return MockObject */ - private function getPaymentMock(string $paymentProviderCode): PHPUnit_Framework_MockObject_MockObject + private function getPaymentMock(string $paymentProviderCode): MockObject { $abstractMethod = $this->getMockBuilder(AbstractMethod::class) ->disableOriginalConstructor() @@ -759,10 +753,10 @@ private function getPaymentMock(string $paymentProviderCode): PHPUnit_Framework_ /** * Return Product Mock. * - * @param Simple|PHPUnit_Framework_MockObject_MockObject $simpleProductTypeMock - * @return PHPUnit_Framework_MockObject_MockObject + * @param Simple|MockObject $simpleProductTypeMock + * @return MockObject */ - private function getProductMock($simpleProductTypeMock): PHPUnit_Framework_MockObject_MockObject + private function getProductMock($simpleProductTypeMock): MockObject { $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() @@ -777,10 +771,10 @@ private function getProductMock($simpleProductTypeMock): PHPUnit_Framework_MockO * Return Quote Item Mock. * * @param string $productType - * @param \Magento\Catalog\Model\Product|PHPUnit_Framework_MockObject_MockObject $productMock - * @return PHPUnit_Framework_MockObject_MockObject + * @param \Magento\Catalog\Model\Product|MockObject $productMock + * @return MockObject */ - private function getQuoteItemMock($productType, $productMock): PHPUnit_Framework_MockObject_MockObject + private function getQuoteItemMock($productType, $productMock): MockObject { $quoteItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class) ->disableOriginalConstructor() @@ -795,16 +789,16 @@ private function getQuoteItemMock($productType, $productMock): PHPUnit_Framework /** * Return Quote Address Item Mock * - * @param \Magento\Quote\Model\Quote\Item|PHPUnit_Framework_MockObject_MockObject $quoteItemMock + * @param \Magento\Quote\Model\Quote\Item|MockObject $quoteItemMock * @param string $productType * @param array $infoBuyRequest - * @return PHPUnit_Framework_MockObject_MockObject + * @return MockObject */ private function getQuoteAddressItemMock( $quoteItemMock, string $productType, array $infoBuyRequest - ): PHPUnit_Framework_MockObject_MockObject { + ): MockObject { $quoteAddressItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\Item::class) ->disableOriginalConstructor() ->setMethods(['getQuoteItem', 'setProductType', 'setProductOptions', 'getParentItem']) @@ -819,7 +813,7 @@ private function getQuoteAddressItemMock( /** * Return Quote Addresses Mock - * @param \Magento\Quote\Model\Quote\Address\Item|PHPUnit_Framework_MockObject_MockObject $quoteAddressItemMock + * @param \Magento\Quote\Model\Quote\Address\Item|MockObject $quoteAddressItemMock * @param int $addressTotal * @return array */ @@ -865,8 +859,8 @@ private function getQuoteAddressesMock($quoteAddressItemMock, int $addressTotal) * Set data for Quote Mock. * * @param string $paymentProviderCode - * @param Address|PHPUnit_Framework_MockObject_MockObject $shippingAddressMock - * @param Address|PHPUnit_Framework_MockObject_MockObject $billingAddressMock + * @param Address|MockObject $shippingAddressMock + * @param Address|MockObject $billingAddressMock * * @return void */ @@ -890,16 +884,16 @@ private function setQuoteMockData(string $paymentProviderCode, $shippingAddressM /** * Return Order Mock. * - * @param OrderAddressInterface|PHPUnit_Framework_MockObject_MockObject $orderAddressMock - * @param OrderPaymentInterface|PHPUnit_Framework_MockObject_MockObject $orderPaymentMock - * @param \Magento\Sales\Model\Order\Item|PHPUnit_Framework_MockObject_MockObject $orderItemMock - * @return PHPUnit_Framework_MockObject_MockObject + * @param OrderAddressInterface|MockObject $orderAddressMock + * @param OrderPaymentInterface|MockObject $orderPaymentMock + * @param \Magento\Sales\Model\Order\Item|MockObject $orderItemMock + * @return MockObject */ private function getOrderMock( $orderAddressMock, $orderPaymentMock, $orderItemMock - ): PHPUnit_Framework_MockObject_MockObject { + ): MockObject { $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) ->disableOriginalConstructor() ->setMethods( @@ -989,20 +983,33 @@ public function testCreateOrdersCountryNotPresentInAllowedListException(): void public function testValidateMinimumAmountMultiAddressFalse(): void { $addressMock = $this->createMock(\Magento\Quote\Model\Quote\Address::class); - $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( - ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(true, false); - $this->scopeConfigMock->expects($this->exactly(2))->method('getValue')->withConsecutive( - ['sales/minimum_order/amount', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/tax_including', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(100, false); + $this->scopeConfigMock->expects($this->exactly(2)) + ->method('isSetFlag') + ->withConsecutive( + ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(true, false); - $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); - $this->quoteMock->expects($this->once())->method('getStoreId')->willReturn(1); - $this->quoteMock->expects($this->once())->method('getAllAddresses')->willReturn([$addressMock]); - $addressMock->expects($this->once())->method('getBaseSubtotalWithDiscount')->willReturn(101); + $this->scopeConfigMock->expects($this->exactly(2)) + ->method('getValue') + ->withConsecutive( + ['sales/minimum_order/amount', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/tax_including', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(100, false); + + $this->checkoutSessionMock->expects($this->atLeastOnce()) + ->method('getQuote') + ->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once()) + ->method('getStoreId') + ->willReturn(1); + $this->quoteMock->expects($this->once()) + ->method('getAllAddresses') + ->willReturn([$addressMock]); + $addressMock->expects($this->once()) + ->method('getBaseSubtotalWithDiscount') + ->willReturn(101); $this->assertTrue($this->model->validateMinimumAmount()); } @@ -1014,13 +1021,20 @@ public function testValidateMinimumAmountMultiAddressFalse(): void */ public function testValidateMinimumAmountMultiAddressTrue(): void { - $this->scopeConfigMock->expects($this->exactly(2))->method('isSetFlag')->withConsecutive( - ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], - ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] - )->willReturnOnConsecutiveCalls(true, true); + $this->scopeConfigMock->expects($this->exactly(2)) + ->method('isSetFlag') + ->withConsecutive( + ['sales/minimum_order/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE], + ['sales/minimum_order/multi_address', \Magento\Store\Model\ScopeInterface::SCOPE_STORE] + )->willReturnOnConsecutiveCalls(true, true); + + $this->checkoutSessionMock->expects($this->atLeastOnce()) + ->method('getQuote') + ->willReturn($this->quoteMock); + $this->quoteMock->expects($this->once()) + ->method('validateMinimumAmount') + ->willReturn(false); - $this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock); - $this->quoteMock->expects($this->once())->method('validateMinimumAmount')->willReturn(false); $this->assertFalse($this->model->validateMinimumAmount()); } @@ -1028,11 +1042,10 @@ public function testValidateMinimumAmountMultiAddressTrue(): void * Return Extension Attributes Mock. * * @param ShippingAssignment $shippingAssignmentMock - * @return CartExtension|PHPUnit_Framework_MockObject_MockObject + * @return CartExtension|MockObject */ - private function getExtensionAttributesMock( - ShippingAssignment $shippingAssignmentMock - ): PHPUnit_Framework_MockObject_MockObject { + private function getExtensionAttributesMock(ShippingAssignment $shippingAssignmentMock): MockObject + { $extensionAttributesMock = $this->getMockBuilder(CartExtension::class) ->setMethods(['setShippingAssignments']) ->getMock(); @@ -1049,9 +1062,9 @@ private function getExtensionAttributesMock( /** * Return Shipping Assignment Mock. * - * @return ShippingAssignment | PHPUnit_Framework_MockObject_MockObject + * @return ShippingAssignment | MockObject */ - private function getShippingAssignmentMock(): PHPUnit_Framework_MockObject_MockObject + private function getShippingAssignmentMock(): MockObject { $shippingAssignmentMock = $this->getMockBuilder(ShippingAssignment::class) ->disableOriginalConstructor() @@ -1101,9 +1114,9 @@ private function mockShippingAssignment(): void * Return Customer Address Mock * * @param $customerAddressId - * @return Address | PHPUnit_Framework_MockObject_MockObject + * @return Address | MockObject */ - private function getCustomerAddressMock($customerAddressId): PHPUnit_Framework_MockObject_MockObject + private function getCustomerAddressMock($customerAddressId): MockObject { $customerAddressMock = $this->getMockBuilder(Address::class) ->setMethods(['getId']) @@ -1120,9 +1133,9 @@ private function getCustomerAddressMock($customerAddressId): PHPUnit_Framework_M * Return Simple Mock. * * @param string $className - * @return PHPUnit_Framework_MockObject_MockObject + * @return MockObject */ - private function createSimpleMock($className): PHPUnit_Framework_MockObject_MockObject + private function createSimpleMock($className): MockObject { return $this->getMockBuilder($className) ->disableOriginalConstructor() @@ -1133,9 +1146,9 @@ private function createSimpleMock($className): PHPUnit_Framework_MockObject_Mock * Return Currency Mock. * * @param $shippingPrice - * @return PHPUnit_Framework_MockObject_MockObject + * @return MockObject */ - private function getCurrencyMock($shippingPrice): PHPUnit_Framework_MockObject_MockObject + private function getCurrencyMock($shippingPrice): MockObject { $currencyMock = $this->getMockBuilder(Currency::class) ->disableOriginalConstructor() From 12feb34d275c64a66066deafb2b17004acb6d429 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych Date: Tue, 28 Jan 2020 11:10:59 +0200 Subject: [PATCH 316/666] refactore private methods to match docblock standart --- .../Unit/Model/Checkout/Type/MultishippingTest.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index 397ea8a59e2aa..a3a0b8c227a61 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -794,11 +794,8 @@ private function getQuoteItemMock($productType, $productMock): MockObject * @param array $infoBuyRequest * @return MockObject */ - private function getQuoteAddressItemMock( - $quoteItemMock, - string $productType, - array $infoBuyRequest - ): MockObject { + private function getQuoteAddressItemMock($quoteItemMock, string $productType, array $infoBuyRequest): MockObject + { $quoteAddressItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\Item::class) ->disableOriginalConstructor() ->setMethods(['getQuoteItem', 'setProductType', 'setProductOptions', 'getParentItem']) @@ -889,11 +886,8 @@ private function setQuoteMockData(string $paymentProviderCode, $shippingAddressM * @param \Magento\Sales\Model\Order\Item|MockObject $orderItemMock * @return MockObject */ - private function getOrderMock( - $orderAddressMock, - $orderPaymentMock, - $orderItemMock - ): MockObject { + private function getOrderMock($orderAddressMock, $orderPaymentMock, $orderItemMock): MockObject + { $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) ->disableOriginalConstructor() ->setMethods( From 00750f42d2404b63f2fad22e3510fd8a363d2838 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" Date: Tue, 28 Jan 2020 11:32:24 +0200 Subject: [PATCH 317/666] fix static --- .../Catalog/Model/CategoryLinkRepository.php | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php index ae30efdee6e18..f8de9a37f4ed7 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkRepository.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkRepository.php @@ -6,11 +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, - \Magento\Catalog\Api\CategoryListDeleteBySkuInterface +/** + * @inheritdoc + */ +class CategoryLinkRepository implements CategoryLinkRepositoryInterface, CategoryListDeleteBySkuInterface { /** * @var CategoryRepository @@ -18,32 +26,32 @@ class CategoryLinkRepository implements \Magento\Catalog\Api\CategoryLinkReposit protected $categoryRepository; /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface + * @var ProductRepositoryInterface */ protected $productRepository; /** - * @var \Magento\Catalog\Model\ResourceModel\Product + * @var Product */ private $productResource; /** - * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\ResourceModel\Product $productResource + * @param CategoryRepositoryInterface $categoryRepository + * @param ProductRepositoryInterface $productRepository + * @param Product $productResource */ public function __construct( - \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\ResourceModel\Product $productResource = null + CategoryRepositoryInterface $categoryRepository, + ProductRepositoryInterface $productRepository, + Product $productResource = null ) { $this->categoryRepository = $categoryRepository; $this->productRepository = $productRepository; - $this->productResource = $productResource ?? \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Catalog\Model\ResourceModel\Product::class); + $this->productResource = $productResource ?? ObjectManager::getInstance()->get(Product::class); } /** - * {@inheritdoc} + * @inheritdoc */ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -69,7 +77,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $pro } /** - * {@inheritdoc} + * @inheritdoc */ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $productLink) { @@ -77,7 +85,7 @@ public function delete(\Magento\Catalog\Api\Data\CategoryProductLinkInterface $p } /** - * {@inheritdoc} + * @inheritdoc */ public function deleteByIds($categoryId, $sku) { @@ -112,7 +120,7 @@ public function deleteByIds($categoryId, $sku) } /** - * {@inheritDoc} + * @inheritdoc */ public function deleteBySkus(int $categoryId, array $productSkuList): bool { From b8480b8b890d0ce589d08c58c9c911764d4e64d4 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" Date: Tue, 28 Jan 2020 10:30:26 +0200 Subject: [PATCH 318/666] fix static --- .../web/css/source/module/checkout/_shipping.less | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less index f054140c0e1b2..8f2092713b718 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less @@ -211,12 +211,6 @@ } } } - - #shipping-method-buttons-container { - .button { - margin-top: 2px; - } - } } // @@ -302,6 +296,9 @@ .action { &.primary { margin: 0; + &.button { + margin-top: 2px; + } } } } From 471b3f87748152ac6affb0bfc0787b81c2a7ca4f Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Tue, 28 Jan 2020 11:03:54 +0200 Subject: [PATCH 319/666] MC-23633: Catalog Inventory modal refactor --- .../Model/Stock/StockItemModifyChecker.php | 70 ++++++++++ ...gInventoryChangeManageStockActionGroup.xml | 24 ++++ .../Stock/StockItemModifyCheckerTest.php | 132 ++++++++++++++++++ .../Form/Modifier/AdvancedInventory.php | 1 + .../Form/Modifier/AdvancedInventoryModal.php | 70 ++++++++++ .../CatalogInventory/etc/adminhtml/di.xml | 11 ++ .../adminhtml/ui_component/product_form.xml | 68 ++++++--- .../js/components/use-config-min-sale-qty.js | 4 +- .../web/js/components/use-config-settings.js | 25 +++- .../Product/Form/Modifier/ConfigurableQty.php | 6 +- .../Product/Form/Modifier/StockData.php | 14 +- .../web/js/components/qty-configurable.js | 45 ++++++ .../js/components/qty-configurable.test.js | 107 ++++++++++++++ 13 files changed, 536 insertions(+), 41 deletions(-) create mode 100644 app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php create mode 100644 app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/AdminCatalogInventoryChangeManageStockActionGroup.xml create mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php create mode 100644 app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventoryModal.php create mode 100644 app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.js create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.test.js diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php new file mode 100644 index 0000000000000..ca8869c6ec5e6 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php @@ -0,0 +1,70 @@ +stockItemRepository = $stockItemRepository; + $this->arrayUtils = $arrayUtils; + $this->skippedAttributes = $skippedAttributes; + } + + /** + * Check if stock item is modified. + * + * @param StockItem $model + * @return bool + */ + public function isModified($model): bool + { + if (!$model->getId()) { + return true; + } + $stockItem = $this->stockItemRepository->get($model->getId()); + $stockItemData = $stockItem->getData(); + $modelData = $model->getData(); + foreach ($this->skippedAttributes as $attribute) { + unset($stockItemData[$attribute], $modelData[$attribute]); + } + $diff = $this->arrayUtils->recursiveDiff($stockItemData, $modelData); + + return !empty($diff); + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/AdminCatalogInventoryChangeManageStockActionGroup.xml b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/AdminCatalogInventoryChangeManageStockActionGroup.xml new file mode 100644 index 0000000000000..2c38f14f53379 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Mftf/ActionGroup/AdminCatalogInventoryChangeManageStockActionGroup.xml @@ -0,0 +1,24 @@ + + + + + + + Opens advanced inventory modal if it has not opened yet. Sets Manage stock value. + + + + + + + + + + + diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php new file mode 100644 index 0000000000000..5e4617ff47193 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php @@ -0,0 +1,132 @@ +stockItemRepository = $this->createPartialMock(StockItemRepository::class, ['get']); + $this->arrayUtils = $this->createPartialMock(ArrayUtils::class, ['recursiveDiff']); + $this->stockItemModel = $this->createPartialMock(StockItem::class, ['getId', 'getData']); + + $this->model = $objectManager->getObject( + StockItemModifyChecker::class, + [ + 'stockItemRepository' => $this->stockItemRepository, + 'arrayUtils' => $this->arrayUtils, + 'skippedAttributes' => [StockItemInterface::LOW_STOCK_DATE], + ] + ); + } + + /** + * Test for IsModified method when data is not modified. + * + * @return void + */ + public function testIsModifiedForNotModifiedModel(): void + { + $itemFromRepository = [ + 'id' => 1, + 'low_stock_date' => '01.01.2020', + 'qty' => 100, + ]; + $model = [ + 'id' => 1, + 'low_stock_date' => '01.01.2021', + 'qty' => 100 + ]; + $this->stockItemModel->expects($this->exactly(2))->method('getId')->willReturn($model['id']); + $this->stockItemRepository->expects($this->once())->method('get')->willReturn($this->stockItemModel); + $this->stockItemModel->expects($this->exactly(2)) + ->method('getData') + ->willReturnOnConsecutiveCalls($itemFromRepository, $model); + $this->arrayUtils->expects($this->once())->method('recursiveDiff')->willReturn([]); + + $this->assertFalse($this->model->isModified($this->stockItemModel)); + } + + /** + * Test for IsModified method when model is new. + * + * @return void + */ + public function testIsModifiedWhenModelIsNew(): void + { + $this->stockItemModel->expects($this->once())->method('getId')->willReturn(null); + $this->stockItemRepository->expects($this->never())->method('get'); + + $this->assertTrue($this->model->isModified($this->stockItemModel)); + } + + /** + * Test for IsModified method when found difference between data. + * + * @return void + */ + public function testIsModifiedWhenDifferenceFound(): void + { + $itemFromRepository = [ + 'id' => 1, + 'low_stock_date' => '01.01.2020', + 'qty' => 100, + ]; + $model = [ + 'id' => 1, + 'low_stock_date' => '01.01.2021', + 'qty' => 99 + ]; + $this->stockItemModel->expects($this->exactly(2))->method('getId')->willReturn($model['id']); + $this->stockItemRepository->expects($this->once())->method('get')->willReturn($this->stockItemModel); + $this->stockItemModel->expects($this->exactly(2)) + ->method('getData') + ->willReturnOnConsecutiveCalls($itemFromRepository, $model); + $this->arrayUtils->expects($this->once())->method('recursiveDiff')->willReturn(['qty' => 100]); + + $this->assertTrue($this->model->isModified($this->stockItemModel)); + } +} diff --git a/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php index aafde14a28584..38a33b75f552a 100644 --- a/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php +++ b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventory.php @@ -242,6 +242,7 @@ private function prepareMeta() 'handleChanges' => '${$.provider}:data.product.stock_data.is_qty_decimal', ], 'sortOrder' => 10, + 'disabled' => $this->locator->getProduct()->isLockedAttribute($fieldCode), ]; $advancedInventoryButton['arguments']['data']['config'] = [ 'displayAsLink' => true, diff --git a/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventoryModal.php b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventoryModal.php new file mode 100644 index 0000000000000..76194b0710441 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Ui/DataProvider/Product/Form/Modifier/AdvancedInventoryModal.php @@ -0,0 +1,70 @@ +locator = $locator; + } + + /** + * @inheritdoc + */ + public function modifyMeta(array $meta) + { + $this->meta = $meta; + $this->prepareMeta(); + + return $this->meta; + } + + /** + * @inheritdoc + */ + public function modifyData(array $data) + { + return $data; + } + + /** + * Modify Advanced Inventory Modal meta. + * + * @return array + */ + private function prepareMeta(): array + { + $product = $this->locator->getProduct(); + $readOnly = (bool)$product->getInventoryReadonly(); + + $this->meta['advanced_inventory_modal']['children']['stock_data']['arguments'] + ['data']['config']['disabled'] = $readOnly; + + return $this->meta; + } +} diff --git a/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml b/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml index 28035de29bc2e..d4dd1b1647416 100644 --- a/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml @@ -37,10 +37,21 @@ Magento\CatalogInventory\Ui\DataProvider\Product\Form\Modifier\AdvancedInventory 20 + + Magento\CatalogInventory\Ui\DataProvider\Product\Form\Modifier\AdvancedInventoryModal + 900 + + + + + Magento\CatalogInventory\Api\Data\StockItemInterface::LOW_STOCK_DATE + + + diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml index c77c77a5183d0..27ce26cabc627 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml +++ b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml @@ -49,6 +49,9 @@ [GLOBAL] manage_stock + + ${$.parentName}.use_config_${$.index}:disableParent + @@ -410,9 +426,9 @@ ${$.provider}:data.product.stock_data.backorders - - ${$.parentName}.backorders:disabled - + + ns = ${ $.ns }, index = stock_data:disabled + @@ -450,6 +466,9 @@ notify_stock_qty + + ${$.parentName}.use_config_${$.index}:disableParent + @@ -465,9 +484,9 @@ ${$.provider}:data.product.stock_data.notify_stock_qty - - ${$.parentName}.notify_stock_qty:disabled - + + ns = ${ $.ns }, index = stock_data:disabled + @@ -500,6 +519,9 @@ [GLOBAL] enable_qty_increments + + ${$.parentName}.use_config_${$.index}:disableParent + diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-min-sale-qty.js b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-min-sale-qty.js index 4ac1d5ed2d294..c7ca38f05f707 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-min-sale-qty.js +++ b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-min-sale-qty.js @@ -37,7 +37,7 @@ define([ /** * @inheritdoc */ - 'onCheckedChanged': function (newChecked) { + onCheckedChanged: function (newChecked) { var valueFromConfig = this.valueFromConfig(); if (newChecked && (_.isArray(valueFromConfig) && valueFromConfig.length === 0 || valueFromConfig === 1)) { @@ -49,7 +49,7 @@ define([ this.changeVisibleDisabled(this.inputField, true, true, null); this.changeVisibleDisabled(this.dynamicRowsField, false, true, null); } else { - this.changeVisibleDisabled(this.inputField, true, false, null); + this.changeVisibleDisabled(this.inputField, true, this.disabled() || false, null); this.changeVisibleDisabled(this.dynamicRowsField, false, true, null); } diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-settings.js b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-settings.js index f91797448fa55..e121743b0f69f 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-settings.js +++ b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/use-config-settings.js @@ -11,7 +11,15 @@ define([ return checkbox.extend({ defaults: { valueFromConfig: '', - linkedValue: '' + linkedValue: '', + disableParent: false, + listens: { + disabled: 'processState', + checked: 'processState onCheckedChanged' + }, + imports: { + readOnly: 'ns = ${ $.ns }, index = stock_data:disabled' + } }, /** @@ -20,13 +28,24 @@ define([ initObservable: function () { return this ._super() - .observe(['valueFromConfig', 'linkedValue']); + .observe(['valueFromConfig', 'linkedValue', 'disableParent']); + }, + + /** + * Handle checked and disabled changes to calculate disableParent value + */ + processState: function () { + this.disableParent(this.checked() || this.readOnly); + + if (this.readOnly) { + this.disable(); + } }, /** * @inheritdoc */ - 'onCheckedChanged': function (newChecked) { + onCheckedChanged: function (newChecked) { if (newChecked) { this.linkedValue(this.valueFromConfig()); } diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableQty.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableQty.php index ade56edeb3dfc..6eb65efa2ecae 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableQty.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableQty.php @@ -41,10 +41,8 @@ public function modifyMeta(array $meta) 'arguments' => [ 'data' => [ 'config' => [ - 'imports' => [ - 'disabled' => '!ns = ${ $.ns }, index = ' - . ConfigurablePanel::CONFIGURABLE_MATRIX . ':isEmpty', - ], + 'component' => 'Magento_ConfigurableProduct/js/' . + 'components/qty-configurable' ], ], ], diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/StockData.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/StockData.php index 58b58b11c1b1c..db51e7eebefc4 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/StockData.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/StockData.php @@ -28,7 +28,7 @@ public function __construct(LocatorInterface $locator) } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyData(array $data) { @@ -36,7 +36,7 @@ public function modifyData(array $data) } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyMeta(array $meta) { @@ -72,15 +72,7 @@ public function modifyMeta(array $meta) ], ]; - $meta['advanced_inventory_modal'] = [ - 'children' => [ - 'stock_data' => [ - 'children' => [ - 'qty' => $config, - ], - ], - ], - ]; + $meta['advanced_inventory_modal']['children']['stock_data']['children']['qty'] = $config; } return $meta; diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.js new file mode 100644 index 0000000000000..6b3840bdec450 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.js @@ -0,0 +1,45 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'Magento_Ui/js/form/element/abstract' +], function (Abstract) { + 'use strict'; + + return Abstract.extend({ + defaults: { + imports: { + isConfigurable: '!ns = ${ $.ns }, index = configurable-matrix:isEmpty' + } + }, + + /** @inheritdoc */ + initialize: function () { + this._super(); + // resolve initial disable state + this.handleQtyValue(this.isConfigurable); + + /** important to set this listener in initialize because of a different order of processing. + * Do not move to defaults->listens section */ + this.setListeners({ + isConfigurable: 'handleQtyValue' + }); + + return this; + }, + + /** + * Disable and clear Qty if product type changed to configurable + * + * @param {String} isConfigurable + */ + handleQtyValue: function (isConfigurable) { + this.disabled(!!this.isUseDefault() || isConfigurable); + + if (isConfigurable) { + this.clear(); + } + } + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.test.js new file mode 100644 index 0000000000000..1c81c9fabf85e --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/qty-configurable.test.js @@ -0,0 +1,107 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define(['squire'], function (Squire) { + 'use strict'; + + var injector = new Squire(), + Component, + params = { + name: 'qty-element', + dataScope: '', + value: 1000, + setListeners: jasmine.createSpy().and.callFake(function () { + return this; + }), + setLinks: jasmine.createSpy().and.callFake(function () { + this.isConfigurable = false; + + return this; + }) + }; + + beforeEach(function (done) { + injector.require( + ['Magento_ConfigurableProduct/js/components/qty-configurable'], function (QtyConfigurable) { + Component = QtyConfigurable; + done(); + }); + }); + + afterEach(function () { + try { + injector.remove(); + injector.clean(); + } catch (e) { + } + }); + + describe('Magento_ConfigurableProduct/js/components/qty-configurable', function () { + it('Product is not configurable by default', function () { + var component = new Component(params); + + expect(component.disabled()).toBeFalsy(); + expect(component.value()).toEqual(1000); + }); + + it('State of component does not changed', function () { + var component = new Component(params); + + expect(component.disabled()).toBeFalsy(); + + component.value(99); + component.handleQtyValue(false); + + expect(component.disabled()).toBeFalsy(); + expect(component.value()).toEqual(99); + }); + + it('Product changed to configurable', function () { + var component = new Component(params); + + expect(component.disabled()).toBeFalsy(); + expect(component.value()).toEqual(1000); + + component.handleQtyValue(true); + + expect(component.disabled()).toBeTruthy(); + expect(component.value()).toEqual(''); + }); + + it('Product is configurable by default', function () { + var component = new Component($.extend({}, params, { + // eslint-disable-next-line max-nested-callbacks + setLinks: jasmine.createSpy().and.callFake(function () { + this.isConfigurable = true; + + return this; + }) + })); + + expect(component.disabled()).toBeTruthy(); + expect(component.value()).toEqual(''); + }); + + it('Product changed from configurable to another one', function () { + var component = new Component($.extend({}, params, { + // eslint-disable-next-line max-nested-callbacks + setLinks: jasmine.createSpy().and.callFake(function () { + this.isConfigurable = true; + + return this; + }) + })); + + expect(component.disabled()).toBeTruthy(); + expect(component.value()).toEqual(''); + + component.value(100); + component.handleQtyValue(false); + + expect(component.disabled()).toBeFalsy(); + expect(component.value()).toEqual(100); + }); + }); +}); From 776b544c25ea451fea9f7b332d64c6f8bd04048a Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Tue, 28 Jan 2020 11:52:42 +0200 Subject: [PATCH 320/666] Fix small typo in test --- .../Test/Unit/Model/Checkout/Type/MultishippingTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index a3a0b8c227a61..c7f85a9edacb4 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -330,7 +330,7 @@ public function testSetShippingItemsInformation(): void } /** - * Verefi set shipping items information for address leak + * Verify set shipping items information for address leak * * @return void * @throws LocalizedException From 4fbd865b77f0da776e993a0bcf8278fd54b31b3d Mon Sep 17 00:00:00 2001 From: Ihor Sviziev Date: Tue, 28 Jan 2020 11:56:37 +0200 Subject: [PATCH 321/666] Fix variable name in test --- .../Test/Unit/Model/Checkout/Type/MultishippingTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index c7f85a9edacb4..747d88353f022 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -931,7 +931,7 @@ private function getOrderMock($orderAddressMock, $orderPaymentMock, $orderItemMo */ public function testCreateOrdersCountryNotPresentInAllowedListException(): void { - $ExceptionMessage = 'Some addresses can\'t be used due to the configurations for specific countries.'; + $exceptionMessage = 'Some addresses can\'t be used due to the configurations for specific countries.'; $abstractMethod = $this->getMockBuilder(AbstractMethod::class) ->disableOriginalConstructor() @@ -964,7 +964,7 @@ public function testCreateOrdersCountryNotPresentInAllowedListException(): void ->willReturn($paymentMock); $this->quoteMock->method('getAllShippingAddresses') ->willReturn([$shippingAddressMock]); - $this->expectExceptionMessage($ExceptionMessage); + $this->expectExceptionMessage($exceptionMessage); $this->model->createOrders(); } From f01776e61c022ec932e3470e6f7bfa8a0b233f14 Mon Sep 17 00:00:00 2001 From: Andrii Kalinich <51681435+engcom-Echo@users.noreply.github.com> Date: Mon, 27 Jan 2020 15:52:16 +0200 Subject: [PATCH 322/666] Update RedirectTest.php --- .../Unit/Controller/Store/RedirectTest.php | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) 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 319620f3c6a02..1124a66fe7a40 100755 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -7,6 +7,7 @@ namespace Magento\Store\Test\Unit\Controller\Store; +use Magento\Framework\App\Action\Context; use Magento\Framework\App\ActionInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\Response\RedirectInterface; @@ -117,18 +118,23 @@ protected function setUp() ->willReturnSelf(); $objectManager = new ObjectManagerHelper($this); - + $context = $objectManager->getObject( + Context::class, + [ + '_request' => $this->requestMock, + '_redirect' => $this->redirectMock, + '_response' => $this->responseMock, + ] + ); $this->redirectController = $objectManager->getObject( Redirect::class, [ - 'storeRepository' => $this->storeRepositoryMock, - 'storeResolver' => $this->storeResolverMock, - 'messageManager' => $this->messageManagerMock, - '_request' => $this->requestMock, - '_redirect' => $this->redirectMock, - '_response' => $this->responseMock, - 'sidResolver' => $this->sidResolverMock, - 'hashGenerator' => $this->hashGeneratorMock + 'storeRepository' => $this->storeRepositoryMock, + 'storeResolver' => $this->storeResolverMock, + 'messageManager' => $this->messageManagerMock, + 'sidResolver' => $this->sidResolverMock, + 'hashGenerator' => $this->hashGeneratorMock, + 'context' => $context, ] ); } @@ -146,13 +152,16 @@ protected function setUp() public function testRedirect(string $defaultStoreViewCode, string $storeCode): void { $this->requestMock - ->expects($this->any()) - ->method('getParam')->willReturnMap( - [ - [StoreResolver::PARAM_NAME, null, $storeCode], - ['___from_store', null, $defaultStoreViewCode], - [ActionInterface::PARAM_NAME_URL_ENCODED, null, $defaultStoreViewCode] - ] + ->expects($this->exactly(3)) + ->method('getParam') + ->withConsecutive( + [StoreResolver::PARAM_NAME], + ['___from_store'], + [ActionInterface::PARAM_NAME_URL_ENCODED] + )->willReturnOnConsecutiveCalls( + $storeCode, + $defaultStoreViewCode, + $defaultStoreViewCode ); $this->storeRepositoryMock ->expects($this->once()) @@ -162,7 +171,7 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v $this->formStoreMock ->expects($this->once()) ->method('getCode') - ->willReturnSelf(); + ->willReturn($defaultStoreViewCode); $this->sidResolverMock ->expects($this->once()) ->method('getUseSessionInUrl') @@ -172,7 +181,6 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v ->method('generateHash') ->with($this->formStoreMock) ->willReturn([]); - $this->redirectMock ->expects($this->once()) ->method('redirect') @@ -182,12 +190,11 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v ['_nosid' => true, '_query' => [ 'uenc' => $defaultStoreViewCode, - '___from_store' => $this->formStoreMock, + '___from_store' => $defaultStoreViewCode, '___store' => $storeCode ] ] - ) - ->willReturnSelf(); + ); $this->assertEquals(null, $this->redirectController->execute()); } @@ -204,15 +211,13 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v public function testRedirectWithThrowsException(string $defaultStoreViewCode, string $storeCode): void { $this->requestMock - ->expects($this->at(0)) - ->method('getParam') - ->with(StoreResolver::PARAM_NAME) - ->willReturn($storeCode); - $this->requestMock - ->expects($this->at(1)) - ->method('getParam') - ->with('___from_store') - ->willReturn($defaultStoreViewCode); + ->expects($this->exactly(2)) + ->method('getParam')->willReturnMap( + [ + [StoreResolver::PARAM_NAME, null, $storeCode], + ['___from_store', null, $defaultStoreViewCode] + ] + ); $this->storeRepositoryMock ->expects($this->once()) ->method('get') @@ -269,7 +274,7 @@ public function testRedirectTargetIsNull(): void public function getConfigDataProvider(): array { return [ - [ self::DEFAULT_STORE_VIEW_CODE, self::STORE_CODE ] + [self::DEFAULT_STORE_VIEW_CODE, self::STORE_CODE] ]; } } From 6f14ca23b1299c3c4a9963011264ee49e67abfcf Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Tue, 28 Jan 2020 12:47:03 +0200 Subject: [PATCH 323/666] Minor changes --- .../Command/TemplateHintsStatusCommand.php | 15 +++++++-------- .../Command/TemplateHintsStatusCommandTest.php | 13 ++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 01c4fe42e083e..42e2d214a330c 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -7,19 +7,18 @@ namespace Magento\Developer\Console\Command; +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Console\Cli; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\Config\ReinitableConfigInterface; -use Magento\Framework\Console\Cli; /** * Command to show frontend template hints status */ class TemplateHintsStatusCommand extends Command { - const COMMAND_NAME = 'dev:template-hints:status'; const TEMPLATE_HINTS_STOREFRONT_PATH = 'dev/debug/template_hints_storefront'; @@ -27,6 +26,7 @@ class TemplateHintsStatusCommand extends Command * @var ScopeConfigInterface */ private $scopeConfig; + /** * @var ReinitableConfigInterface */ @@ -41,8 +41,7 @@ class TemplateHintsStatusCommand extends Command public function __construct( ScopeConfigInterface $scopeConfig, ReinitableConfigInterface $reinitableConfig - ) - { + ) { parent::__construct(); $this->scopeConfig = $scopeConfig; $this->reinitableConfig = $reinitableConfig; @@ -51,7 +50,7 @@ public function __construct( /** * @inheritdoc */ - protected function configure() + public function configure() { $this->setName(self::COMMAND_NAME) ->setDescription('Show frontend template hints status.'); @@ -63,7 +62,7 @@ protected function configure() * @inheritdoc * @throws \InvalidArgumentException */ - protected function execute(InputInterface $input, OutputInterface $output) + public function execute(InputInterface $input, OutputInterface $output) { $this->reinitableConfig->reinit(); $templateHintsStatus = diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php index 7c6ab356b4ada..e3db485635e18 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -7,11 +7,11 @@ namespace Magento\Developer\Test\Unit\Console\Command; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Tester\CommandTester; use Magento\Developer\Console\Command\TemplateHintsStatusCommand; -use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Tester\CommandTester; /** * Class TemplateHintsStatusCommandTest @@ -35,7 +35,7 @@ class TemplateHintsStatusCommandTest extends TestCase private $reinitableConfigMock; /** - * TemplateHintsStatusCommandTest setup + * @inheritDoc */ protected function setUp() { @@ -46,11 +46,10 @@ protected function setUp() $this->scopeConfigMock, $this->reinitableConfigMock ); - } /** - * Test execution + * Verify execution */ public function testExecute() { @@ -62,4 +61,4 @@ public function testExecute() $tester->getStatusCode() ); } -} \ No newline at end of file +} From ac66ee7062a416a366ffaa8a7ec53f11ddf68354 Mon Sep 17 00:00:00 2001 From: Michele Fantetti Date: Tue, 28 Jan 2020 11:59:16 +0100 Subject: [PATCH 324/666] Add frontend template hints status command after suggestions --- .../Unit/Console/Command/TemplateHintsStatusCommandTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php index e3db485635e18..f3acb5d2e1f5e 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -10,6 +10,7 @@ use Magento\Developer\Console\Command\TemplateHintsStatusCommand; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Console\Cli; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; @@ -57,7 +58,7 @@ public function testExecute() $tester->execute([]); $this->assertEquals( - 0, + Cli::RETURN_SUCCESS, $tester->getStatusCode() ); } From 1bb9a791e6fbf74a68cea5aeac48da0da2406e86 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Tue, 28 Jan 2020 13:53:10 +0200 Subject: [PATCH 325/666] MC-30391: Category not considered Configurable product in cart rule --- .../Model/Rule/Condition/ProductTest.php | 51 +------------------ 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php index 6f4a298f04553..066f30667b53c 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Condition/ProductTest.php @@ -6,10 +6,6 @@ namespace Magento\SalesRule\Model\Rule\Condition; -use Magento\Quote\Api\CartRepositoryInterface; -use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Quote\Api\Data\CartInterface; -use Magento\SalesRule\Api\RuleRepositoryInterface; use Magento\Framework\Registry; use Magento\SalesRule\Model\Rule; @@ -18,6 +14,8 @@ */ class ProductTest extends \PHPUnit\Framework\TestCase { + use ConditionHelper; + /** * @var \Magento\Framework\ObjectManagerInterface */ @@ -133,51 +131,6 @@ public function testValidateQtySalesRuleWithConfigurable() ); } - /** - * Gets quote by reserved order id. - * - * @param string $reservedOrderId - * @return CartInterface - */ - private function getQuote($reservedOrderId) - { - /** @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); - } - - /** - * Gets rule by name. - * - * @param string $name - * @return \Magento\SalesRule\Model\Rule - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - private function getSalesRule(string $name): \Magento\SalesRule\Model\Rule - { - /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ - $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); - $searchCriteria = $searchCriteriaBuilder->addFilter('name', $name) - ->create(); - - /** @var CartRepositoryInterface $quoteRepository */ - $ruleRepository = $this->objectManager->get(RuleRepositoryInterface::class); - $items = $ruleRepository->getList($searchCriteria)->getItems(); - - $rule = array_pop($items); - /** @var \Magento\SalesRule\Model\Converter\ToModel $converter */ - $converter = $this->objectManager->get(\Magento\SalesRule\Model\Converter\ToModel::class); - - return $converter->toModel($rule); - } - /** * Ensure that SalesRules filtering on quote items quantity validates configurable product parent category correctly * From 1251f01b4ab88d5ef70447667e1f482feb01b055 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" Date: Tue, 28 Jan 2020 15:03:32 +0200 Subject: [PATCH 326/666] magento/magento2#26455: fix mftf --- ...onfigFieldSetGuestNotAllowedActionGroup.xml | 18 ------------------ ...LinkDisplayedForGuestSubscriptionNoTest.xml | 8 ++------ 2 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml diff --git a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml b/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml deleted file mode 100644 index a6242797cf3c6..0000000000000 --- a/app/code/Magento/Newsletter/Test/Mftf/ActionGroup/AdminNewsletterConfigFieldSetGuestNotAllowedActionGroup.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml index 0780363b682cd..3288de47dd4b9 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/VerifyRegistredLinkDisplayedForGuestSubscriptionNoTest.xml @@ -10,12 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - - - - - - + From aaa9e01c1be1db482ca0b78e617f3e8a6fd192a6 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Tue, 28 Jan 2020 15:36:09 +0200 Subject: [PATCH 327/666] Fix Unit Test. --- .../Test/Unit/Model/Js/DataProviderTest.php | 140 +++++++++--------- 1 file changed, 68 insertions(+), 72 deletions(-) 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 aee0ac0f10ba5..c9a0dc2373697 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; /** * @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,22 +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 + * Verify data translate. * * @param array $config * @return void * @dataProvider configDataProvider - * - * @throws \Magento\Framework\Exception\LocalizedException */ - public function testGetData(array $config) + public function testGetData(array $config): void { $themePath = 'blank'; $areaCode = 'adminhtml'; @@ -140,14 +144,14 @@ public function testGetData(array $config) } /** - * Verify Get Data Throwing Exception + * Verify get data throwing exception. * * @param array $config - * @expectedException \Magento\Framework\Exception\LocalizedException - * + * @return void * @dataProvider configDataProvider + * @expectedException \Magento\Framework\Exception\LocalizedException */ - public function testGetDataThrowingException(array $config) + public function testGetDataThrowingException(array $config): void { $themePath = 'blank'; $areaCode = 'adminhtml'; @@ -156,7 +160,6 @@ public function testGetDataThrowingException(array $config) $this->fileReadMock->expects($this->once()) ->method('readAll') ->willReturn('content1$.mage.__("hello1")content1'); - $this->appStateMock->expects($this->once()) ->method('getAreaCode') ->willReturn($areaCode); @@ -166,11 +169,9 @@ public function testGetDataThrowingException(array $config) $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')); @@ -179,47 +180,42 @@ public function testGetDataThrowingException(array $config) } /** - * Config Data Provider + * Config data provider. * * @return array */ public function configDataProvider(): array { return [ - [ - [ - 'patterns' => [ - '~\$\.mage\.__\(([\'"])(.+?)\1\)~', - '~i18n\:\s*(["\'])(.*?)(?.+?)(? [ - 'hello1' => 'hello1translated', - 'hello2' => 'hello2translated', - 'hello3' => 'hello3translated', - 'hello4' => 'hello4translated' - ], - - 'contentsMap' => - [ - 'content1$.mage.__("hello1")content1', - 'content2$.mage.__("hello2")content2', - 'content2$.mage.__("hello4")content4', - 'content2$.mage.__("hello3")content3', - ], - - 'translateMap' => [ - [['hello1'], [], 'hello1translated'], - [['hello2'], [], 'hello2translated'], - [['hello3'], [], 'hello3translated'], - [['hello4'], [], 'hello4translated'] - ] + [ + [ + 'patterns' => [ + '~\$\.mage\.__\(([\'"])(.+?)\1\)~', + '~i18n\:\s*(["\'])(.*?)(?.+?)(? [ + 'hello1' => 'hello1translated', + 'hello2' => 'hello2translated', + 'hello3' => 'hello3translated', + 'hello4' => 'hello4translated', + ], + 'contentsMap' => [ + 'content1$.mage.__("hello1")content1', + 'content2$.mage.__("hello2")content2', + 'content2$.mage.__("hello4")content4', + 'content2$.mage.__("hello3")content3', + ], + 'translateMap' => [ + [['hello1'], [], 'hello1translated'], + [['hello2'], [], 'hello2translated'], + [['hello3'], [], 'hello3translated'], + [['hello4'], [], 'hello4translated'], + ] + ], + ] ]; } } From 5d57110df249f75c2d47e1856882af595967c078 Mon Sep 17 00:00:00 2001 From: Viktor Petryk Date: Tue, 28 Jan 2020 15:37:11 +0200 Subject: [PATCH 328/666] MC-25260: A wrong behaviour of a chart order --- .../Magento/Backend/Block/Dashboard/Graph.php | 39 +++---- .../Model/ResourceModel/Order/Collection.php | 1 + .../Block/Dashboard/Tab/OrdersTest.php | 94 ++++++++++++++++ .../Sales/_files/order_list_with_invoice.php | 103 ++++++++++++++++++ .../order_list_with_invoice_rollback.php | 8 ++ 5 files changed, 220 insertions(+), 25 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_list_with_invoice_rollback.php diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index b76421e4e6f67..145c3394efd7b 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' @@ -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/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/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..f5b730173e596 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php @@ -0,0 +1,94 @@ +objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->graphBlock = $this->layout->createBlock(Graph::class); + } + + /** + * @magentoDbIsolation disabled + * @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()); + $chartUrlSegments = explode('&', $decodedChartUrl); + $this->assertEquals($expectedAxisRange, $this->getUrlParamData($chartUrlSegments, '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 array $chartUrlSegments + * @param string $paramName + * @return string + */ + private function getUrlParamData(array $chartUrlSegments, string $paramName): string + { + $urlParams = []; + foreach ($chartUrlSegments as $chartUrlSegment) { + list($paramKey, $paramValue) = explode('=', $chartUrlSegment); + $urlParams[$paramKey] = $paramValue; + } + + return $urlParams[$paramName] ?? ''; + } +} 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 @@ +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 @@ + Date: Tue, 28 Jan 2020 14:20:04 +0200 Subject: [PATCH 329/666] Fix RedirectTest --- .../Unit/Controller/Store/RedirectTest.php | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) 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 1124a66fe7a40..88de664f3bb29 100755 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -94,14 +94,34 @@ class RedirectTest extends TestCase */ protected function setUp() { - $this->requestMock = $this->createMock(RequestInterface::class); - $this->redirectMock = $this->createMock(RedirectInterface::class); - $this->storeResolverMock = $this->createMock(StoreResolverInterface::class); - $this->storeRepositoryMock = $this->createMock(StoreRepositoryInterface::class); - $this->messageManagerMock = $this->createMock(ManagerInterface::class); - $this->responseMock = $this->createMock(ResponseInterface::class); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getParam']) + ->getMockForAbstractClass(); + $this->redirectMock = $this->getMockBuilder(RedirectInterface::class) + ->disableOriginalConstructor() + ->setMethods(['redirect']) + ->getMockForAbstractClass(); + $this->storeResolverMock = $this->getMockBuilder(StoreResolverInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCurrentStoreId']) + ->getMockForAbstractClass(); + $this->storeRepositoryMock = $this->getMockBuilder(StoreRepositoryInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getById', 'get']) + ->getMockForAbstractClass(); + $this->messageManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['addErrorMessage']) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder(ResponseInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->formStoreMock = $this->createMock(Store::class); - $this->sidResolverMock = $this->createMock(SidResolverInterface::class); + $this->sidResolverMock = $this->getMockBuilder(SidResolverInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getUseSessionInUrl']) + ->getMockForAbstractClass(); $this->hashGeneratorMock = $this->createMock(HashGenerator::class); $this->currentStoreMock = $this->getMockBuilder(Store::class) @@ -124,6 +144,7 @@ protected function setUp() '_request' => $this->requestMock, '_redirect' => $this->redirectMock, '_response' => $this->responseMock, + 'messageManager' => $this->messageManagerMock, ] ); $this->redirectController = $objectManager->getObject( @@ -131,7 +152,6 @@ protected function setUp() [ 'storeRepository' => $this->storeRepositoryMock, 'storeResolver' => $this->storeResolverMock, - 'messageManager' => $this->messageManagerMock, 'sidResolver' => $this->sidResolverMock, 'hashGenerator' => $this->hashGeneratorMock, 'context' => $context, @@ -147,7 +167,6 @@ protected function setUp() * * @dataProvider getConfigDataProvider * @return void - * @throws NoSuchEntityException */ public function testRedirect(string $defaultStoreViewCode, string $storeCode): void { @@ -206,17 +225,18 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v * @param string $storeCode * @return void * @dataProvider getConfigDataProvider - * @throws NoSuchEntityException */ public function testRedirectWithThrowsException(string $defaultStoreViewCode, string $storeCode): void { $this->requestMock ->expects($this->exactly(2)) - ->method('getParam')->willReturnMap( - [ - [StoreResolver::PARAM_NAME, null, $storeCode], - ['___from_store', null, $defaultStoreViewCode] - ] + ->method('getParam') + ->withConsecutive( + [StoreResolver::PARAM_NAME], + ['___from_store'] + )->willReturnOnConsecutiveCalls( + $storeCode, + $defaultStoreViewCode ); $this->storeRepositoryMock ->expects($this->once()) @@ -245,20 +265,19 @@ public function testRedirectWithThrowsException(string $defaultStoreViewCode, st * Verify redirect target is null * * @return void - * @throws NoSuchEntityException */ public function testRedirectTargetIsNull(): void { $this->requestMock - ->expects($this->at(0)) - ->method('getParam') - ->with(StoreResolver::PARAM_NAME) - ->willReturn(null); - $this->requestMock - ->expects($this->at(1)) + ->expects($this->exactly(2)) ->method('getParam') - ->with('___from_store') - ->willReturnSelf(); + ->withConsecutive( + [StoreResolver::PARAM_NAME], + ['___from_store'] + )->willReturnOnConsecutiveCalls( + null, + null + ); $this->storeRepositoryMock ->expects($this->never()) ->method('get'); From 6d985af3486280a5a672ef32681a6cdb2a148aa3 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh Date: Tue, 28 Jan 2020 16:11:26 +0200 Subject: [PATCH 330/666] MC-30739: Custom customer address attribute code showing on checkout --- .../Checkout/view/frontend/web/js/view/billing-address.js | 8 +++++--- .../js/view/shipping-address/address-renderer/default.js | 8 +++++--- .../view/shipping-information/address-renderer/default.js | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index e728a5c0fcdd5..f850386890470 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -255,9 +255,11 @@ function ( return attribute.label; } - resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { - value: attribute.value - }); + if (typeof this.source.get('customAttributes') !== 'undefined') { + resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { + value: attribute.value + }); + } return resultAttribute && resultAttribute.label || attribute.value; } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js index 939a2af1a25aa..1f8cc90fe1622 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js @@ -65,9 +65,11 @@ define([ return attribute.label; } - resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { - value: attribute.value - }); + if (typeof this.source.get('customAttributes') !== 'undefined') { + resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { + value: attribute.value + }); + } return resultAttribute && resultAttribute.label || attribute.value; }, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js index 009178cbb19b9..6ec9fde554dc2 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js @@ -42,9 +42,11 @@ define([ return attribute.label; } - resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { - value: attribute.value - }); + if (typeof this.source.get('customAttributes') !== 'undefined') { + resultAttribute = _.findWhere(this.source.get('customAttributes')[attribute['attribute_code']], { + value: attribute.value + }); + } return resultAttribute && resultAttribute.label || attribute.value; } From bc06501851838ca9a07a3fc437b778c46366b4e9 Mon Sep 17 00:00:00 2001 From: Serhii Balko Date: Tue, 28 Jan 2020 16:13:17 +0200 Subject: [PATCH 331/666] MC-30148: Temporary files are not deleted after exporting products --- .../ImportExport/Model/Export/Adapter/Csv.php | 19 ++--- .../AbstractProductExportImportTestCase.php | 17 +++-- .../Model/Export/Adapter/CsvTest.php | 70 +++++++++++++++++++ 3 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Adapter/CsvTest.php diff --git a/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php b/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php index 25081b5797c25..09b17371ae4e8 100644 --- a/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php +++ b/app/code/Magento/ImportExport/Model/Export/Adapter/Csv.php @@ -5,13 +5,16 @@ */ namespace Magento\ImportExport\Model\Export\Adapter; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem\File\Write; + /** * Export adapter csv. * * @api * @since 100.0.2 */ -class Csv extends \Magento\ImportExport\Model\Export\Adapter\AbstractAdapter +class Csv extends AbstractAdapter { /** * Field delimiter. @@ -30,21 +33,20 @@ class Csv extends \Magento\ImportExport\Model\Export\Adapter\AbstractAdapter /** * Source file handler. * - * @var \Magento\Framework\Filesystem\File\Write + * @var Write */ protected $_fileHandler; /** - * {@inheritdoc } + * Object destructor */ - public function __construct(\Magento\Framework\Filesystem $filesystem, $destination = null) + public function __destruct() { - register_shutdown_function([$this, 'destruct']); - parent::__construct($filesystem, $destination); + $this->destruct(); } /** - * Object destructor. + * Clean cached values * * @return void */ @@ -52,6 +54,7 @@ public function destruct() { if (is_object($this->_fileHandler)) { $this->_fileHandler->close(); + $this->_directoryHandle->delete($this->_destination); } } @@ -96,7 +99,7 @@ public function getFileExtension() public function setHeaderCols(array $headerColumns) { if (null !== $this->_headerCols) { - throw new \Magento\Framework\Exception\LocalizedException(__('The header column names are already set.')); + throw new LocalizedException(__('The header column names are already set.')); } if ($headerColumns) { foreach ($headerColumns as $columnName) { diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php index d3a2e4c53f246..eecdcdf038cf8 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php @@ -7,6 +7,7 @@ use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\ImportExport\Model\Export\Adapter\AbstractAdapter; use Magento\Store\Model\Store; /** @@ -62,6 +63,11 @@ abstract class AbstractProductExportImportTestCase extends \PHPUnit\Framework\Te 'tax_class_id', ]; + /** + * @var AbstractAdapter + */ + private $writer; + /** * @inheritdoc */ @@ -367,7 +373,7 @@ protected function executeImportReplaceTest( * Export products in the system. * * @param \Magento\CatalogImportExport\Model\Export\Product|null $exportProduct - * @return string Return exported file name + * @return string Return exported file */ private function exportProducts(\Magento\CatalogImportExport\Model\Export\Product $exportProduct = null) { @@ -376,12 +382,11 @@ private function exportProducts(\Magento\CatalogImportExport\Model\Export\Produc $exportProduct = $exportProduct ?: $this->objectManager->create( \Magento\CatalogImportExport\Model\Export\Product::class ); - $exportProduct->setWriter( - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\ImportExport\Model\Export\Adapter\Csv::class, - ['fileSystem' => $this->fileSystem, 'destination' => $csvfile] - ) + $this->writer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\ImportExport\Model\Export\Adapter\Csv::class, + ['fileSystem' => $this->fileSystem, 'destination' => $csvfile] ); + $exportProduct->setWriter($this->writer); $this->assertNotEmpty($exportProduct->export()); return $csvfile; diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Adapter/CsvTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Adapter/CsvTest.php new file mode 100644 index 0000000000000..b874e55aea9ed --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Model/Export/Adapter/CsvTest.php @@ -0,0 +1,70 @@ +objectManager = Bootstrap::getObjectManager(); + $this->csv = $this->objectManager->create( + Csv::class, + ['destination' => $this->destination] + ); + } + + /** + * Test to destruct export adapter + */ + public function testDestruct(): void + { + /** @var Filesystem $fileSystem */ + $fileSystem = $this->objectManager->get(Filesystem::class); + $directoryHandle = $fileSystem->getDirectoryRead(DirectoryList::VAR_DIR); + /** Assert that the destination file is present after construct */ + $this->assertFileExists( + $directoryHandle->getAbsolutePath($this->destination), + 'The destination file was\'t created after construct' + ); + /** Assert that the destination file was removed after destruct */ + $this->csv = null; + $this->assertFileNotExists( + $directoryHandle->getAbsolutePath($this->destination), + 'The destination file was\'t removed after destruct' + ); + } +} From a1ac22c564de3fff5ab3a66d24d26c592e194e58 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Tue, 28 Jan 2020 17:02:29 +0200 Subject: [PATCH 332/666] MC-23633: Catalog Inventory modal refactor --- .../Stock/StockItemModifyCheckerTest.php | 92 ++++++++++--------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php index 5e4617ff47193..73f3a8af29666 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php @@ -38,7 +38,7 @@ class StockItemModifyCheckerTest extends TestCase private $stockItemModel; /** - * @var ArrayUtils|MockObject + * @var ArrayUtils */ private $arrayUtils; @@ -50,7 +50,7 @@ protected function setUp() $objectManager = new ObjectManager($this); $this->stockItemRepository = $this->createPartialMock(StockItemRepository::class, ['get']); - $this->arrayUtils = $this->createPartialMock(ArrayUtils::class, ['recursiveDiff']); + $this->arrayUtils = $objectManager->getObject(ArrayUtils::class); $this->stockItemModel = $this->createPartialMock(StockItem::class, ['getId', 'getData']); $this->model = $objectManager->getObject( @@ -63,33 +63,6 @@ protected function setUp() ); } - /** - * Test for IsModified method when data is not modified. - * - * @return void - */ - public function testIsModifiedForNotModifiedModel(): void - { - $itemFromRepository = [ - 'id' => 1, - 'low_stock_date' => '01.01.2020', - 'qty' => 100, - ]; - $model = [ - 'id' => 1, - 'low_stock_date' => '01.01.2021', - 'qty' => 100 - ]; - $this->stockItemModel->expects($this->exactly(2))->method('getId')->willReturn($model['id']); - $this->stockItemRepository->expects($this->once())->method('get')->willReturn($this->stockItemModel); - $this->stockItemModel->expects($this->exactly(2)) - ->method('getData') - ->willReturnOnConsecutiveCalls($itemFromRepository, $model); - $this->arrayUtils->expects($this->once())->method('recursiveDiff')->willReturn([]); - - $this->assertFalse($this->model->isModified($this->stockItemModel)); - } - /** * Test for IsModified method when model is new. * @@ -106,27 +79,60 @@ public function testIsModifiedWhenModelIsNew(): void /** * Test for IsModified method when found difference between data. * + * @param array $itemFromRepository + * @param array $model + * @param bool $expectedResult * @return void + * @dataProvider stockItemModelDataProvider */ - public function testIsModifiedWhenDifferenceFound(): void - { - $itemFromRepository = [ - 'id' => 1, - 'low_stock_date' => '01.01.2020', - 'qty' => 100, - ]; - $model = [ - 'id' => 1, - 'low_stock_date' => '01.01.2021', - 'qty' => 99 - ]; + public function testIsModified( + array $itemFromRepository, + array $model, + bool $expectedResult + ): void { $this->stockItemModel->expects($this->exactly(2))->method('getId')->willReturn($model['id']); $this->stockItemRepository->expects($this->once())->method('get')->willReturn($this->stockItemModel); $this->stockItemModel->expects($this->exactly(2)) ->method('getData') ->willReturnOnConsecutiveCalls($itemFromRepository, $model); - $this->arrayUtils->expects($this->once())->method('recursiveDiff')->willReturn(['qty' => 100]); - $this->assertTrue($this->model->isModified($this->stockItemModel)); + $this->assertEquals($expectedResult, $this->model->isModified($this->stockItemModel)); + } + + /** + * Data provider for testIsModified. + * + * @return array + */ + public function stockItemModelDataProvider(): array + { + return [ + 'Model is modified' => [ + 'stockItemFromRepository' => [ + 'id' => 1, + 'low_stock_date' => '01.01.2020', + 'qty' => 100, + ], + 'model' => [ + 'id' => 1, + 'low_stock_date' => '01.01.2021', + 'qty' => 99, + ], + 'expectedResult' => true, + ], + 'Model is not modified' => [ + 'stockItemFromRepository' => [ + 'id' => 1, + 'low_stock_date' => '01.01.2020', + 'qty' => 100, + ], + 'model' => [ + 'id' => 1, + 'low_stock_date' => '01.01.2021', + 'qty' => 100, + ], + 'expectedResult' => false, + ], + ]; } } From 270e8e4e579aedc4ddbc285731de907d35e23d78 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Tue, 28 Jan 2020 18:49:52 +0200 Subject: [PATCH 333/666] Small adjustments --- .../Csp/Test/Unit/Model/Mode/ConfigManagerTest.php | 8 +++----- .../Csp/Test/Unit/Model/PolicyRendererPoolTest.php | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php index c574abc1bad59..a41c03b512fc5 100644 --- a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -20,8 +20,6 @@ use RuntimeException; /** - * Class ConfigManagerTest - * * Test for \Magento\Csp\Model\Mode\ConfigManager */ class ConfigManagerTest extends TestCase @@ -71,9 +69,6 @@ protected function setUp() * Test throwing an exception for non storefront or admin areas * * @return void - * - * @expectedExceptionMessage CSP can only be configured for storefront or admin area - * @expectedException RuntimeException */ public function testThrownExceptionForCrontabArea() { @@ -81,6 +76,9 @@ public function testThrownExceptionForCrontabArea() ->method('getAreaCode') ->willReturn(Area::AREA_CRONTAB); + $this->expectExceptionMessage('CSP can only be configured for storefront or admin area'); + $this->expectException(RuntimeException::class); + $this->model->getConfigured(); } diff --git a/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php index 2b551d4b8dcaf..84ee8584ebf59 100644 --- a/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php +++ b/app/code/Magento/Csp/Test/Unit/Model/PolicyRendererPoolTest.php @@ -17,8 +17,6 @@ use RuntimeException; /** - * Class PolicyRendererPoolTest - * * Test for \Magento\Csp\Model\PolicyRendererPool */ class PolicyRendererPoolTest extends TestCase @@ -66,9 +64,6 @@ protected function setUp() * Test throwing an exception for not found policy renders * * @return void - * - * @expectedExceptionMessage Failed to find a renderer for policy - * @expectedException RuntimeException */ public function testThrownExceptionForNotFoundPolicyRenders() { @@ -76,6 +71,9 @@ public function testThrownExceptionForNotFoundPolicyRenders() ->method('getId') ->willReturn(static::STUB_POLICY_ID); + $this->expectExceptionMessage('Failed to find a renderer for policy'); + $this->expectException(RuntimeException::class); + $this->model->getRenderer($this->policyMock); } From 2e346af25356e3681dd76fada865aae563676a69 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz Date: Tue, 28 Jan 2020 18:41:53 +0100 Subject: [PATCH 334/666] Semantic Version Checker fix --- app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php index 37bc356e32db5..ac66392efe5dc 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Upsell.php @@ -158,7 +158,7 @@ public function getItemCollection() /** * Get collection items * - * @return DataObject[] + * @return \Magento\Framework\DataObject[] */ public function getItems() { @@ -232,7 +232,7 @@ public function getIterableItem() * * @param string $type * @param int $limit - * @return $this + * @return \Magento\Catalog\Block\Product\ProductList\Upsell */ public function setItemLimit($type, $limit) { From eb979046e02e5e44a88deae892f665b28791e77e Mon Sep 17 00:00:00 2001 From: Sathish Date: Wed, 29 Jan 2020 00:14:23 +0530 Subject: [PATCH 335/666] array_map updated instead of foreach --- app/code/Magento/Fedex/Model/Source/Generic.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Fedex/Model/Source/Generic.php b/app/code/Magento/Fedex/Model/Source/Generic.php index b1c1c0aedb863..a7442f7a18128 100644 --- a/app/code/Magento/Fedex/Model/Source/Generic.php +++ b/app/code/Magento/Fedex/Model/Source/Generic.php @@ -1,5 +1,4 @@ */ class Generic implements \Magento\Framework\Data\OptionSourceInterface { @@ -44,9 +41,14 @@ public function toOptionArray() $configData = $this->_shippingFedex->getCode($this->_code); $arr = []; if ($configData) { - foreach ($configData as $code => $title) { - $arr[] = ['value' => $code, 'label' => $title]; - } + $arr = array_map( + function ($code, $title) { + return [ + 'value' => $code, + 'label' => $title + ]; + }, array_keys($configData), $configData + ); } return $arr; From 74b1d8b24d6c936e2042d6c5dede88b494069764 Mon Sep 17 00:00:00 2001 From: Sathish Date: Wed, 29 Jan 2020 01:13:02 +0530 Subject: [PATCH 336/666] Static test fix --- app/code/Magento/Fedex/Model/Source/Generic.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Fedex/Model/Source/Generic.php b/app/code/Magento/Fedex/Model/Source/Generic.php index a7442f7a18128..c918dd7ad0013 100644 --- a/app/code/Magento/Fedex/Model/Source/Generic.php +++ b/app/code/Magento/Fedex/Model/Source/Generic.php @@ -47,7 +47,9 @@ function ($code, $title) { 'value' => $code, 'label' => $title ]; - }, array_keys($configData), $configData + }, + array_keys($configData), + $configData ); } From e22b34b3e5ae0c2241684298c2dcaafa00f45e5e Mon Sep 17 00:00:00 2001 From: Ajith Date: Wed, 29 Jan 2020 01:54:21 +0530 Subject: [PATCH 337/666] Action group added for existing test --- .../AdminNavigateToPageGridActionGroup.xml | 19 +++++++++++++++ ...reateNewPageWithBasicValuesActionGroup.xml | 24 +++++++++++++++++++ .../VerifyCreatedCmsPageActionGroup.xml | 21 ++++++++++++++++ .../Test/Mftf/Test/AdminCreateCmsPageTest.xml | 23 ++++-------------- 4 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToPageGridActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/CreateNewPageWithBasicValuesActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCreatedCmsPageActionGroup.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToPageGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToPageGridActionGroup.xml new file mode 100644 index 0000000000000..7dc68e7a5a891 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToPageGridActionGroup.xml @@ -0,0 +1,19 @@ + + + + + + + Navigates to CMS page grid. + + + + + + diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/CreateNewPageWithBasicValuesActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/CreateNewPageWithBasicValuesActionGroup.xml new file mode 100644 index 0000000000000..1f9ddf7e70424 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/CreateNewPageWithBasicValuesActionGroup.xml @@ -0,0 +1,24 @@ + + + + + + + Click Add new page button and fills basic information in cms page. Values are hardcoded from _defaultCmsPage. + + + + + + + + + + + diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCreatedCmsPageActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCreatedCmsPageActionGroup.xml new file mode 100644 index 0000000000000..5cbd3bf7072a0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/VerifyCreatedCmsPageActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Verify created cms page in store front. Values are hardcoded from _defaultCmsPage. + + + + + + + + diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index db8b5606cd398..e6fcbab4de644 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -25,25 +25,10 @@ - - - - - - - - - - - - - - - - - - - + + + + From e3c203ad5fb0693c55cd3abc383ef6baa43e8b10 Mon Sep 17 00:00:00 2001 From: Oleh Usik Date: Tue, 28 Jan 2020 23:26:52 +0200 Subject: [PATCH 338/666] Fixed wrong state title --- .../Sales/Block/Status/Grid/Column/State.php | 6 ++-- app/code/Magento/Sales/Model/Order/Config.php | 19 ----------- .../Test/Unit/Model/Order/ConfigTest.php | 32 ------------------- 3 files changed, 3 insertions(+), 54 deletions(-) diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index d2163fae72428..85e32d53c4b72 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -53,9 +53,9 @@ public function getFrameCallback() */ public function decorateState($value, $row, $column, $isExport) { - $status = $row->getStatus(); - if ($value) { - $cell = $value . '[' . $this->_config->getStateLabelByStateAndStatus($value, $status) . ']'; + $states = $this->_config->getStates(); + if (isset($states[$value])) { + $cell = $value . '[' . $states[$value] . ']'; } else { $cell = $value; } diff --git a/app/code/Magento/Sales/Model/Order/Config.php b/app/code/Magento/Sales/Model/Order/Config.php index 92681f3ecf181..7dbddcd0a16c4 100644 --- a/app/code/Magento/Sales/Model/Order/Config.php +++ b/app/code/Magento/Sales/Model/Order/Config.php @@ -300,23 +300,4 @@ protected function _getStatuses($visibility) } return $this->statuses[(bool) $visibility]; } - - /** - * Retrieve label by state and status - * - * @param string $state - * @param string $status - * @return \Magento\Framework\Phrase|string - * @since 100.2.0 - */ - public function getStateLabelByStateAndStatus($state, $status) - { - foreach ($this->_getCollection() as $item) { - if ($item->getData('state') == $state && $item->getData('status') == $status) { - $label = $item->getData('label'); - return __($label); - } - } - return $state; - } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php index feee2816b2cd4..c1a271ef2b591 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php @@ -116,38 +116,6 @@ public function testGetInvisibleOnFrontStatuses() $this->assertSame($expectedResult, $result); } - /** - * @return void - */ - public function testGetStateLabelByStateAndStatus() - { - $statuses = [ - new DataObject( - [ - 'status' => 'fraud', - 'state' => 'processing', - 'label' => 'Suspected Fraud', - ] - ), - new DataObject( - [ - 'status' => 'processing', - 'state' => 'processing', - 'label' => 'Processing', - ] - ) - ]; - $collectionMock = $this->createPartialMock(Collection::class, ['create', 'joinStates']); - $this->orderStatusCollectionFactoryMock->expects($this->once()) - ->method('create') - ->will($this->returnValue($collectionMock)); - $collectionMock->expects($this->once()) - ->method('joinStates') - ->will($this->returnValue($statuses)); - $result = $this->salesConfig->getStateLabelByStateAndStatus('processing', 'fraud'); - $this->assertSame('Suspected Fraud', $result->getText()); - } - /** * Test get statuses * From 1cb2bb63b1fd59b4fb2452330693d15fa39d3b03 Mon Sep 17 00:00:00 2001 From: Joan He Date: Tue, 28 Jan 2020 19:56:33 -0600 Subject: [PATCH 339/666] B2B-319: Remove crons and queue consumers - remove purchase order convert to order --- .../Adminhtml/Order/Create/SaveTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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.']), From f5f0827836fd250aa473ad8e9d795f46dc42c35c Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov Date: Wed, 29 Jan 2020 10:05:55 +0200 Subject: [PATCH 340/666] MC-23633: Catalog Inventory modal refactor --- ...temModifyChecker.php => StockItemChecker.php} | 2 +- ...yCheckerTest.php => StockItemCheckerTest.php} | 16 ++++++++-------- .../CatalogInventory/etc/adminhtml/di.xml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) rename app/code/Magento/CatalogInventory/Model/Stock/{StockItemModifyChecker.php => StockItemChecker.php} (98%) rename app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/{StockItemModifyCheckerTest.php => StockItemCheckerTest.php} (90%) diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemChecker.php similarity index 98% rename from app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php rename to app/code/Magento/CatalogInventory/Model/Stock/StockItemChecker.php index ca8869c6ec5e6..e3a9c48b27155 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemModifyChecker.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemChecker.php @@ -14,7 +14,7 @@ /** * Verifies Stock item model changes. */ -class StockItemModifyChecker +class StockItemChecker { /** * @var StockItemRepositoryInterface diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemCheckerTest.php similarity index 90% rename from app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php rename to app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemCheckerTest.php index 73f3a8af29666..0f2568a2e213d 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemModifyCheckerTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemCheckerTest.php @@ -8,7 +8,7 @@ namespace Magento\CatalogInventory\Test\Unit\Model\Stock; use Magento\CatalogInventory\Api\Data\StockItemInterface; -use Magento\CatalogInventory\Model\Stock\StockItemModifyChecker; +use Magento\CatalogInventory\Model\Stock\StockItemChecker; use Magento\CatalogInventory\Model\Stock\Item as StockItem; use Magento\CatalogInventory\Model\Stock\StockItemRepository; use Magento\Framework\Stdlib\ArrayUtils; @@ -17,13 +17,13 @@ use PHPUnit\Framework\TestCase; /** - * Unit test for StockItemModifyChecker. - * @see StockItemModifyChecker + * Unit test for StockItemChecker. + * @see StockItemChecker */ -class StockItemModifyCheckerTest extends TestCase +class StockItemCheckerTest extends TestCase { /** - * @var StockItemModifyChecker + * @var StockItemChecker */ private $model; @@ -54,7 +54,7 @@ protected function setUp() $this->stockItemModel = $this->createPartialMock(StockItem::class, ['getId', 'getData']); $this->model = $objectManager->getObject( - StockItemModifyChecker::class, + StockItemChecker::class, [ 'stockItemRepository' => $this->stockItemRepository, 'arrayUtils' => $this->arrayUtils, @@ -64,7 +64,7 @@ protected function setUp() } /** - * Test for IsModified method when model is new. + * Test for isModified method when model is new. * * @return void */ @@ -77,7 +77,7 @@ public function testIsModifiedWhenModelIsNew(): void } /** - * Test for IsModified method when found difference between data. + * Test for isModified method when found difference between data. * * @param array $itemFromRepository * @param array $model diff --git a/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml b/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml index d4dd1b1647416..4d90b2159d852 100644 --- a/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogInventory/etc/adminhtml/di.xml @@ -47,7 +47,7 @@ - + Magento\CatalogInventory\Api\Data\StockItemInterface::LOW_STOCK_DATE From e3e06d0b6e18e1884273561c48bd5b4818eb0a36 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Wed, 29 Jan 2020 10:29:29 +0200 Subject: [PATCH 341/666] Removing disabled class --- .../Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml index 353137a4dcb2e..55195698c5dc8 100644 --- a/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/templates/grid.phtml @@ -19,7 +19,7 @@
Date: Wed, 29 Jan 2020 11:44:07 +0200 Subject: [PATCH 342/666] Minor changes --- .../Crontab/Test/Unit/CrontabManagerTest.php | 69 ++++++++++++++----- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php index f6c863d9d9fad..4ee8c89e2b802 100644 --- a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php @@ -3,32 +3,34 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - +declare(strict_types=1); namespace Magento\Framework\Crontab\Test\Unit; +use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Crontab\CrontabManager; use Magento\Framework\Crontab\CrontabManagerInterface; -use Magento\Framework\ShellInterface; -use Magento\Framework\Phrase; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; -use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\DriverPool; +use Magento\Framework\Phrase; +use Magento\Framework\ShellInterface; +use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * Tests crontab manager functionality. */ -class CrontabManagerTest extends \PHPUnit\Framework\TestCase +class CrontabManagerTest extends TestCase { /** - * @var ShellInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ShellInterface|MockObject */ private $shellMock; /** - * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + * @var Filesystem|MockObject */ private $filesystemMock; @@ -38,7 +40,7 @@ class CrontabManagerTest extends \PHPUnit\Framework\TestCase private $crontabManager; /** - * @return void + * @inheritDoc */ protected function setUp() { @@ -53,9 +55,11 @@ protected function setUp() } /** + * Verify get tasks without cronetab. + * * @return void */ - public function testGetTasksNoCrontab() + public function testGetTasksNoCrontab(): void { $exception = new \Exception('crontab: no crontab for user'); $localizedException = new LocalizedException(new Phrase('Some error'), $exception); @@ -69,12 +73,14 @@ public function testGetTasksNoCrontab() } /** + * Verify get tasks. + * * @param string $content * @param array $tasks * @return void * @dataProvider getTasksDataProvider */ - public function testGetTasks($content, $tasks) + public function testGetTasks($content, $tasks): void { $this->shellMock->expects($this->once()) ->method('execute') @@ -85,9 +91,11 @@ public function testGetTasks($content, $tasks) } /** + * Data provider to get tasks. + * * @return array */ - public function getTasksDataProvider() + public function getTasksDataProvider(): array { return [ [ @@ -120,11 +128,13 @@ public function getTasksDataProvider() } /** + * Verify remove tasks with exception. + * * @return void * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Shell error */ - public function testRemoveTasksWithException() + public function testRemoveTasksWithException(): void { $exception = new \Exception('Shell error'); $localizedException = new LocalizedException(new Phrase('Some error'), $exception); @@ -143,12 +153,14 @@ public function testRemoveTasksWithException() } /** + * Verify remove tasks. + * * @param string $contentBefore * @param string $contentAfter * @return void * @dataProvider removeTasksDataProvider */ - public function testRemoveTasks($contentBefore, $contentAfter) + public function testRemoveTasks($contentBefore, $contentAfter): void { $this->shellMock->expects($this->at(0)) ->method('execute') @@ -163,9 +175,11 @@ public function testRemoveTasks($contentBefore, $contentAfter) } /** + * Data provider to remove tasks. + * * @return array */ - public function removeTasksDataProvider() + public function removeTasksDataProvider(): array { return [ [ @@ -195,11 +209,13 @@ public function removeTasksDataProvider() } /** + * Verify save tasks with empty tasks list. + * * @return void * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage The list of tasks is empty. Add tasks and try again. */ - public function testSaveTasksWithEmptyTasksList() + public function testSaveTasksWithEmptyTasksList(): void { $baseDirMock = $this->getMockBuilder(ReadInterface::class) ->getMockForAbstractClass(); @@ -222,11 +238,13 @@ public function testSaveTasksWithEmptyTasksList() } /** + * Verify save tasks with out command. + * * @return void * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage The command shouldn't be empty. Enter and try again. */ - public function testSaveTasksWithoutCommand() + public function testSaveTasksWithoutCommand(): void { $baseDirMock = $this->getMockBuilder(ReadInterface::class) ->getMockForAbstractClass(); @@ -252,13 +270,15 @@ public function testSaveTasksWithoutCommand() } /** + * Verify sava task. + * * @param array $tasks * @param string $content * @param string $contentToSave * @return void * @dataProvider saveTasksDataProvider */ - public function testSaveTasks($tasks, $content, $contentToSave) + public function testSaveTasks($tasks, $content, $contentToSave): void { $baseDirMock = $this->getMockBuilder(ReadInterface::class) ->getMockForAbstractClass(); @@ -291,9 +311,11 @@ public function testSaveTasks($tasks, $content, $contentToSave) } /** + * Data provider to save tasks. + * * @return array */ - public function saveTasksDataProvider() + public function saveTasksDataProvider(): array { $content = '* * * * * /bin/php /var/www/cron.php' . PHP_EOL . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL @@ -354,6 +376,17 @@ public function saveTasksDataProvider() . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"' . PHP_EOL . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], + [ + 'tasks' => [ + ['command' => '{magentoRoot}run.php % cron:run | grep -v "Ran \'jobs\' by schedule"$'] + ], + 'content' => '* * * * * /bin/php /var/www/cron.php', + 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL + . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php' + . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"\$' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, + ], ]; } } From 5b3a1316eb450753d03abbbb5b7b4dbaffa8ced9 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" Date: Wed, 29 Jan 2020 11:55:00 +0200 Subject: [PATCH 343/666] magento/magento2#25249: fix static --- .../Unit/Model/CategoryLinkRepositoryTest.php | 173 ++++++++++++------ 1 file changed, 116 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 3e679fce64421..483eb8d6795bd 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -6,50 +6,71 @@ namespace Magento\Catalog\Test\Unit\Model; -use Magento\Framework\Exception\InputException; +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryProductLinkInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\CategoryLinkRepository; +use Magento\Catalog\Model\ResourceModel\Product; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\Product as ProductModel; +/** + * 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; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $categoryRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $productRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var CategoryProductLinkInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $productLinkMock; + /** + * @var Product|\PHPUnit_Framework_MockObject_MockObject + */ protected $productResourceMock; + /** + * Initialize required data + */ protected function setUp() { - - $this->productResourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + $this->productResourceMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->setMethods(['getProductsIdsBySkus']) ->getMock(); - $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->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->productResourceMock ); } - public function testSave() + /** + * Assign a product to the category + * + * @return void + */ + public function testSave(): void { $categoryId = 42; $productId = 55; @@ -57,10 +78,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) @@ -71,14 +92,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; @@ -86,10 +109,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) @@ -101,20 +124,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(\Magento\Framework\Exception\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) @@ -123,24 +154,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) @@ -150,50 +183,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(\Magento\Framework\Exception\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(\Magento\Framework\Exception\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) @@ -202,17 +246,23 @@ 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)); } - public function testDeleteBySkus() + /** + * Delete by products skus + * + * @return void + */ + public function testDeleteBySkus(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -222,38 +272,44 @@ public function testDeleteBySkus() $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, [$productSku])); } /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage The category doesn't contain the specified products. + * Delete by products skus with `InputException` + * + * @return void */ - public function testDeleteBySkusWithInputException() + public function testDeleteBySkusWithInputException(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + 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(\Magento\Framework\Exception\InputException::class); $this->model->deleteBySkus($categoryId, [$productSku]); } /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - * @expectedExceptionMessage Could not save products "testSku" to category 42 + * Delete by products skus with `CouldNotSaveException` + * + * @return void */ - public function testDeleteSkusIdsWithCouldNotSaveException() + public function testDeleteSkusIdsWithCouldNotSaveException(): void { $categoryId = 42; - $productSku = "testSku"; + $productSku = 'testSku'; $productId = 55; $productPositions = [55 => 1]; $categoryMock = $this->createPartialMock( - \Magento\Catalog\Model\Category::class, + Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] ); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) @@ -264,6 +320,9 @@ public function testDeleteSkusIdsWithCouldNotSaveException() $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(\Magento\Framework\Exception\CouldNotSaveException::class); $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); } } From f4cf91621d7d31203d7fec2c5d0353ab70a10373 Mon Sep 17 00:00:00 2001 From: DmitryTsymbal Date: Wed, 29 Jan 2020 12:05:00 +0200 Subject: [PATCH 344/666] Seasrch Term Redirect --- ...inCreateNewSearchTermEntityActionGroup.xml | 25 +++++++++ .../StoreFrontQuickSearchActionGroup.xml | 20 ++++++++ .../Section/AdminSearchTermFormSection.xml | 18 +++++++ .../Section/AdminSearchTermsGridSection.xml | 14 +++++ ...rontVerifySearchTermEntityRedirectTest.xml | 51 +++++++++++++++++++ 5 files changed, 128 insertions(+) create mode 100644 app/code/Magento/Search/Test/Mftf/ActionGroup/AdminCreateNewSearchTermEntityActionGroup.xml create mode 100644 app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontQuickSearchActionGroup.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermFormSection.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermsGridSection.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminCreateNewSearchTermEntityActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminCreateNewSearchTermEntityActionGroup.xml new file mode 100644 index 0000000000000..5fb8f9c2b6b47 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/AdminCreateNewSearchTermEntityActionGroup.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontQuickSearchActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontQuickSearchActionGroup.xml new file mode 100644 index 0000000000000..aec874e7b6d85 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontQuickSearchActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermFormSection.xml b/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermFormSection.xml new file mode 100644 index 0000000000000..8135ed517c376 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermFormSection.xml @@ -0,0 +1,18 @@ + + + + +
+ + + + + +
+
diff --git a/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermsGridSection.xml b/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermsGridSection.xml new file mode 100644 index 0000000000000..0eeffdb24f94e --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Section/AdminSearchTermsGridSection.xml @@ -0,0 +1,14 @@ + + + + +
+ +
+
diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml new file mode 100644 index 0000000000000..e24a72e5940cf --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml @@ -0,0 +1,51 @@ + + + + + + + + + <description value="Storefront search by created search term with redirect. Verifying if created redirect is working"/> + </annotations> + + <before> + <!-- Login As Admin User --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!-- Navigate To Marketing Search Terms Grid --> + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToSearchTermPage"> + <argument name="menuUiId" value="{{AdminMenuMarketing.dataUiId}}"/> + <argument name="submenuUiId" value="{{AdminMenuMarketingSEOAndSearchSearchTerms.dataUiId}}"/> + </actionGroup> + <!-- Create Custom Search Term With Redirect --> + <actionGroup ref="AdminCreateNewSearchTermEntityActionGroup" stepKey="createSearchTerm"> + <argument name="query" value="{{SearchTerm.query_text}}"/> + <argument name="store" value="{{SearchTerm.store_id}}"/> + <argument name="redirectUrl" value="{{SearchTerm.redirect}}"/> + </actionGroup> + </before> + <after> + <amOnPage url="{{AdminCatalogSearchTermIndexPage.url}}" stepKey="navigateToSearchTermPage"/> + <actionGroup ref="AdminSearchTermFilterBySearchQueryActionGroup" stepKey="findCreatedTerm"> + <argument name="searchQuery" value="{{SearchTerm.query_text}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteCreatedSearchTerm"/> + </after> + + <!-- TEST BODY --> + <!-- Navigate To StoreFront --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + <!-- Fill in Search Field, Submit Search Request --> + <actionGroup ref="StoreFrontQuickSearchActionGroup" stepKey="searchByCreatedTerm"> + <argument name="query" value="{{SearchTerm.query_text}}"/> + </actionGroup> + <!-- Assert Current Url --> + <seeCurrentUrlEquals stepKey="checkUrl" url="{{SearchTerm.redirect}}"/> + </test> +</tests> From f6868655d7cfa3e5eec742a061da3f83b1037a36 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 29 Jan 2020 12:41:19 +0200 Subject: [PATCH 345/666] magento/magento2#25249: fix cs --- .../Unit/Model/CategoryLinkRepositoryTest.php | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 483eb8d6795bd..8543d546b6a6b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -9,10 +9,13 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryProductLinkInterface; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\CategoryLinkRepository; -use Magento\Catalog\Model\ResourceModel\Product; 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 @@ -24,27 +27,27 @@ class CategoryLinkRepositoryTest extends \PHPUnit\Framework\TestCase /** * @var CategoryLinkRepository */ - protected $model; + private $model; /** - * @var CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CategoryRepositoryInterface|MockObject */ - protected $categoryRepositoryMock; + private $categoryRepositoryMock; /** - * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ProductRepositoryInterface|MockObject */ - protected $productRepositoryMock; + private $productRepositoryMock; /** - * @var CategoryProductLinkInterface|\PHPUnit_Framework_MockObject_MockObject + * @var CategoryProductLinkInterface|MockObject */ - protected $productLinkMock; + private $productLinkMock; /** - * @var Product|\PHPUnit_Framework_MockObject_MockObject + * @var Product|MockObject */ - protected $productResourceMock; + private $productResourceMock; /** * Initialize required data @@ -126,7 +129,7 @@ public function testSaveWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->model->save($this->productLinkMock); } @@ -185,7 +188,7 @@ public function testDeleteByIdsWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save product "55" with position 1 to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->model->deleteByIds($categoryId, $productSku); } @@ -216,7 +219,7 @@ public function testDeleteWithInputException(): void $categoryMock->expects($this->never())->method('save'); $this->expectExceptionMessage('The category doesn\'t contain the specified product.'); - $this->expectException(\Magento\Framework\Exception\InputException::class); + $this->expectException(InputException::class); $this->assertTrue($this->model->delete($this->productLinkMock)); } @@ -293,7 +296,7 @@ public function testDeleteBySkusWithInputException(): void ->willReturn($categoryMock); $this->expectExceptionMessage('The category doesn\'t contain the specified products.'); - $this->expectException(\Magento\Framework\Exception\InputException::class); + $this->expectException(InputException::class); $this->model->deleteBySkus($categoryId, [$productSku]); } @@ -322,7 +325,7 @@ public function testDeleteSkusIdsWithCouldNotSaveException(): void $categoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); $this->expectExceptionMessage('Could not save products "testSku" to category 42'); - $this->expectException(\Magento\Framework\Exception\CouldNotSaveException::class); + $this->expectException(CouldNotSaveException::class); $this->assertTrue($this->model->deleteBySkus($categoryId, [$productSku])); } } From 88aa6e2b785dc3fae30ac81447f90e67d63c4a20 Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Wed, 29 Jan 2020 12:41:44 +0200 Subject: [PATCH 346/666] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- ...tProductControlsAreNotVisibleWithoutHoverActionGroup.xml | 4 ++-- ...torefrontProductControlsAreVisibleOnHoverActionGroup.xml | 4 ++-- .../Test/Mftf/Section/StorefrontCategoryMainSection.xml | 6 +++--- ...minFillCatalogProductsListWidgetCategoryActionGroup.xml} | 2 +- .../Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml | 2 -- .../Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml | 2 +- ...AddToWishListIconIsClickableForGuestUserActionGroup.xml} | 4 ++-- 7 files changed, 11 insertions(+), 13 deletions(-) rename app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/{AdminFillCatalogProductsListWidgetOptionsActionGroup.xml => AdminFillCatalogProductsListWidgetCategoryActionGroup.xml} (96%) rename app/code/Magento/Wishlist/Test/Mftf/ActionGroup/{AssertStorefrontAddToWishListIconIsClickableActionGroup.xml => AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml} (81%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml index 8d18c49d6a624..226bb8468d62e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreNotVisibleWithoutHoverActionGroup.xml @@ -13,7 +13,7 @@ </annotations> <dontSeeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsNotVisible"/> - <dontSeeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsNotVisible"/> - <dontSeeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsNotVisible"/> + <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 index 9c26dcecf726a..60d56df04bd2f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductControlsAreVisibleOnHoverActionGroup.xml @@ -13,7 +13,7 @@ </annotations> <seeElement selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="assertAddToCartButtonElementIsVisible"/> - <seeElement selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> - <seeElement selector="{{StorefrontCategoryMainSection.toCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="assertAddToWishListIconIsVisible"/> + <seeElement selector="{{StorefrontCategoryMainSection.addToCompareIconProductInfoHover}}" stepKey="assertAddToCompareIconIsVisible"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 8f2ba2016aea6..e6fc804fcf90c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -18,8 +18,8 @@ <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"/> - <element name="toWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> - <element name="toCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> + <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> + <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> <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"/> @@ -30,7 +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="//div[@class='product-item-info']//a[contains(text(), '{{productName}}')]//..//..//span[@class='price']" parameterized="true"/> + <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//..//..//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/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml similarity index 96% rename from app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml rename to app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml index a5b3078dbdcc4..ecc5780da0e02 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetOptionsActionGroup.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/ActionGroup/AdminFillCatalogProductsListWidgetCategoryActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminFillCatalogProductsListWidgetCategoryActionGroup"> <annotations> - <description>Fill Catalog Products List Widget Category.</description> + <description>Fill catalog products list widget category.</description> </annotations> <arguments> diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml index fde10352ab2ba..f1753f4c0b649 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/StorefrontProductGridUIUpdatesOnDesktopTest.xml @@ -48,8 +48,6 @@ </actionGroup> <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetButton"/> <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveButton"/> - <!-- TODO: REMOVE AFTER FIX MC-29943 --> - <magentoCLI command="indexer:reindex" stepKey="performReindex"/> </before> <after> <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml index 2ec329bf174b3..c221dd62cd7f6 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickInsertWidgetActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminClickInsertWidgetActionGroup"> <annotations> - <description>Click Insert Widget button.</description> + <description>Click "Insert Widget" button in the opened widget popup</description> </annotations> <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetButton"/> diff --git a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml similarity index 81% rename from app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml rename to app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml index 77984a048c5ff..6d2bda0cb9e0b 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableActionGroup.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml @@ -10,11 +10,11 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup"> <annotations> - <description>Assert AddToWishList icon is clickable</description> + <description>Assert "Add to Wish List" icon is clickable in category product listing</description> </annotations> <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> - <click selector="{{StorefrontCategoryMainSection.toWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> + <click selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForErrorMessageIsVisible"/> <see selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="You must login or register to add items to your wishlist." stepKey="assertErrorMessage"/> From 684ae8ec7541f328cc092b1e6e355cd684db501a Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun <d.cheshun@atwix.com> Date: Wed, 29 Jan 2020 13:03:37 +0200 Subject: [PATCH 347/666] Minor code style fixes --- .../Test/StorefrontVerifySearchTermEntityRedirectTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml index e24a72e5940cf..5f21d4364736b 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchTermEntityRedirectTest.xml @@ -38,14 +38,14 @@ <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteCreatedSearchTerm"/> </after> - <!-- TEST BODY --> - <!-- Navigate To StoreFront --> + <!-- TEST BODY --> + <!-- Navigate To StoreFront --> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> - <!-- Fill in Search Field, Submit Search Request --> + <!-- Fill in Search Field, Submit Search Request --> <actionGroup ref="StoreFrontQuickSearchActionGroup" stepKey="searchByCreatedTerm"> <argument name="query" value="{{SearchTerm.query_text}}"/> </actionGroup> - <!-- Assert Current Url --> + <!-- Assert Current Url --> <seeCurrentUrlEquals stepKey="checkUrl" url="{{SearchTerm.redirect}}"/> </test> </tests> From 153688a6de30c441dfab85a2a39e75fec9690941 Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Wed, 29 Jan 2020 13:42:24 +0200 Subject: [PATCH 348/666] MC-30357: [On Pre] [2.2.7] Status Change Doesn't Update the Stock Index ("Update on Schedule" indexers) --- .../Magento/CatalogInventory/etc/mview.xml | 2 ++ .../Model/Import/ProductTest.php | 30 +++++++++++++++++++ ...nventory_stock_item_update_by_schedule.php | 13 ++++++++ ...stock_item_update_by_schedule_rollback.php | 13 ++++++++ 4 files changed, 58 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule_rollback.php diff --git a/app/code/Magento/CatalogInventory/etc/mview.xml b/app/code/Magento/CatalogInventory/etc/mview.xml index 72dda16e8b5bb..338f1fe0610a1 100644 --- a/app/code/Magento/CatalogInventory/etc/mview.xml +++ b/app/code/Magento/CatalogInventory/etc/mview.xml @@ -9,6 +9,8 @@ <view id="cataloginventory_stock" class="Magento\CatalogInventory\Model\Indexer\Stock" group="indexer"> <subscriptions> <table name="cataloginventory_stock_item" entity_column="product_id" /> + <!--Track product status to trigger stock indexer--> + <table name="catalog_product_entity_int" entity_column="entity_id" /> </subscriptions> </view> <view id="catalog_product_price" class="Magento\Catalog\Model\Indexer\Product\Price" group="indexer"> 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 fdbda7e817d56..27b781a5f3c93 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -2968,4 +2968,34 @@ public function testProductStockStatusShouldBeUpdated() $status = $stockRegistry->getStockStatusBySku('simple'); $this->assertEquals(Stock::STOCK_IN_STOCK, $status->getStockStatus()); } + + /** + * Test that product stock status is updated after import on schedule + * + * @magentoDataFixture mediaImportImageFixture + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule.php + * @magentoDbIsolation disabled + */ + public function testProductStockStatusShouldBeUpdatedOnSchedule() + { + /** * @var $indexProcessor \Magento\Indexer\Model\Processor */ + $indexProcessor = $this->objectManager->create(\Magento\Indexer\Model\Processor::class); + /** @var $stockRegistry StockRegistry */ + $stockRegistry = $this->objectManager->create(StockRegistry::class); + /** @var StockRegistryStorage $stockRegistryStorage */ + $stockRegistryStorage = $this->objectManager->get(StockRegistryStorage::class); + $status = $stockRegistry->getStockStatusBySku('simple'); + $this->assertEquals(Stock::STOCK_IN_STOCK, $status->getStockStatus()); + $this->importDataForMediaTest('disable_product.csv'); + $indexProcessor->updateMview(); + $stockRegistryStorage->clean(); + $status = $stockRegistry->getStockStatusBySku('simple'); + $this->assertEquals(Stock::STOCK_OUT_OF_STOCK, $status->getStockStatus()); + $this->importDataForMediaTest('enable_product.csv'); + $indexProcessor->updateMview(); + $stockRegistryStorage->clean(); + $status = $stockRegistry->getStockStatusBySku('simple'); + $this->assertEquals(Stock::STOCK_IN_STOCK, $status->getStockStatus()); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule.php new file mode 100644 index 0000000000000..94e700a778d97 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; +use Magento\TestFramework\Helper\Bootstrap; + +/** * @var $indexerProcessor Processor */ +$indexerProcessor = Bootstrap::getObjectManager()->get(Processor::class); +$indexerProcessor->getIndexer()->setScheduled(true); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule_rollback.php new file mode 100644 index 0000000000000..bd9a07529e8e3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/cataloginventory_stock_item_update_by_schedule_rollback.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; +use Magento\TestFramework\Helper\Bootstrap; + +/** * @var $indexerProcessor Processor */ +$indexerProcessor = Bootstrap::getObjectManager()->get(Processor::class); +$indexerProcessor->getIndexer()->setScheduled(false); From 5c79a9efdf840eb4568e20ee0f54b319eb1833cd Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 29 Jan 2020 14:28:28 +0200 Subject: [PATCH 349/666] Fix Unit Test. --- .../Framework/Crontab/Test/Unit/CrontabManagerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php index 4ee8c89e2b802..4ef00fbb65576 100644 --- a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php @@ -378,13 +378,13 @@ public function saveTasksDataProvider(): array ], [ 'tasks' => [ - ['command' => '{magentoRoot}run.php % cron:run | grep -v "Ran \'jobs\' by schedule"$'] + ['command' => '{magentoRoot}run.php mysqldump db > db-$(date +%F).sql'] ], 'content' => '* * * * * /bin/php /var/www/cron.php', 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . hash("sha256", BP) . PHP_EOL . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php' - . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"\$' . PHP_EOL + . ' mysqldump db > db-\$(date +%%F).sql' . PHP_EOL . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . hash("sha256", BP) . PHP_EOL, ], ]; From 953d9b2f9cd223652c033c2611b8b960628011bd Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 29 Jan 2020 15:00:49 +0200 Subject: [PATCH 350/666] Fix Unit Test. --- .../Store/Test/Unit/Controller/Store/RedirectTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 88de664f3bb29..41ff3de1942af 100755 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -117,7 +117,10 @@ protected function setUp() $this->responseMock = $this->getMockBuilder(ResponseInterface::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->formStoreMock = $this->createMock(Store::class); + $this->formStoreMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); $this->sidResolverMock = $this->getMockBuilder(SidResolverInterface::class) ->disableOriginalConstructor() ->setMethods(['getUseSessionInUrl']) From 4e94687ae0c753d9d8d936b9917a8bd65aad001a Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Wed, 29 Jan 2020 15:18:34 +0200 Subject: [PATCH 351/666] fixed minor code style issues --- app/code/Magento/Sales/Block/Status/Grid/Column/State.php | 2 ++ app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index 85e32d53c4b72..51d9886c79b67 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -6,6 +6,8 @@ namespace Magento\Sales\Block\Status\Grid\Column; /** + * Column State class + * * @api * @since 100.0.2 */ diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php index c1a271ef2b591..2dcc3c2a9fd24 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php @@ -9,7 +9,7 @@ use Magento\Sales\Model\ResourceModel\Order\Status\Collection; /** - * Class ConfigTest + * Test for Magento\Sales\Model\Order\Config class */ class ConfigTest extends \PHPUnit\Framework\TestCase { From c8775638ec0a910ea34e7d77fe6aeb20111d2a99 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 29 Jan 2020 15:52:25 +0200 Subject: [PATCH 352/666] Unit test for Magento\Reports\Observer\CheckoutCartAddProductObserver --- .../CheckoutCartAddProductObserverTest.php | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php diff --git a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php new file mode 100644 index 0000000000000..25c3b62697e5d --- /dev/null +++ b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php @@ -0,0 +1,161 @@ +<?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; +use Magento\Framework\Event\Observer; +use Magento\Quote\Model\Quote\Item as QuoteItem; +use Magento\Reports\Model\Event as ReportsEventModel; +use Magento\Reports\Model\ReportStatus; +use Magento\Reports\Observer\CheckoutCartAddProductObserver; +use Magento\Reports\Observer\EventSaver; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for @see CheckoutCartAddProductObserver + */ +class CheckoutCartAddProductObserverTest extends TestCase +{ + const STUB_QUOTE_PARENT_ITEM_ID = 1; + const STUB_QUOTE_ITEM_ID = 2; + + /** + * @var MockObject|EventSaver + */ + private $eventSaverMock; + + /** + * @var MockObject|ReportStatus + */ + private $reportStatusMock; + + /** + * @var MockObject|Observer + */ + private $eventObserverMock; + + /** + * @var MockObject|Event + */ + private $eventMock; + + /** + * @var MockObject|QuoteItem + */ + private $quoteItemMock; + + /** + * @var CheckoutCartAddProductObserver + */ + private $observer; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->eventSaverMock = $this->createMock(EventSaver::class); + $this->reportStatusMock = $this->createMock(ReportStatus::class); + $this->eventObserverMock = $this->createMock(Observer::class); + $this->quoteItemMock = $this->createMock(QuoteItem::class); + $this->eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getItem']) + ->getMock(); + + $this->observer = new CheckoutCartAddProductObserver( + $this->eventSaverMock, + $this->reportStatusMock + ); + } + + /** + * The case when event has to be successfully saved + */ + public function testExecute() + { + $this->configureMocksWhenReportsEnabled(); + $this->quoteItemMock->expects($this->once()) + ->method('getId') + ->willReturn(null); + $this->quoteItemMock->expects($this->once()) + ->method('getParentItem') + ->willReturn(null); + + $this->eventSaverMock->expects($this->once()) + ->method('save'); + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test the method when 'Product Added To Cart' Report is disabled in configuration + */ + public function testExecuteWhenReportsDisabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->with(ReportsEventModel::EVENT_PRODUCT_TO_CART) + ->willReturn(false); + + $this->checkOriginalMethodIsNeverExecuted(); + } + + /** + * Test when Quote Item has Id + */ + public function testExecuteWithQuoteItemIdSet() + { + $this->configureMocksWhenReportsEnabled(); + $this->quoteItemMock->expects($this->any()) + ->method('getId') + ->willReturn(self::STUB_QUOTE_ITEM_ID); + + $this->checkOriginalMethodIsNeverExecuted(); + } + + /** + * Test when Quote Item has Parent Item set + */ + public function testExecuteWithQuoteParentItemIdSet() + { + $this->configureMocksWhenReportsEnabled(); + $this->quoteItemMock->expects($this->any()) + ->method('getParentItem') + ->willReturn(self::STUB_QUOTE_PARENT_ITEM_ID); + + $this->checkOriginalMethodIsNeverExecuted(); + } + + /** + * Common mocks assertions when Report is enabled in configuration + */ + private function configureMocksWhenReportsEnabled() + { + $this->reportStatusMock->expects($this->once()) + ->method('isReportEnabled') + ->willReturn(true); + $this->eventObserverMock->expects($this->once()) + ->method('getEvent') + ->willReturn($this->eventMock); + $this->eventMock->expects($this->once()) + ->method('getItem') + ->willReturn($this->quoteItemMock); + } + + /** + * Checking that the method will be never executed + */ + private function checkOriginalMethodIsNeverExecuted() + { + $this->eventSaverMock->expects($this->never()) + ->method('save'); + $this->observer->execute($this->eventObserverMock); + } +} From b315f70d8f30262951823f9530a066259cfd0d70 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Wed, 29 Jan 2020 16:22:30 +0200 Subject: [PATCH 353/666] MC-30546: [Magento Cloud] [Question] Tax config query --- .../Sales/Total/Quote/CommonTaxCollector.php | 7 +- .../Model/Sales/Total/Quote/SubtotalTest.php | 311 +++++++++++------- 2 files changed, 202 insertions(+), 116 deletions(-) diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index c70c715d32c1b..55a56bd857a58 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -593,8 +593,11 @@ protected function processProductItems( $total->setSubtotalInclTax($subtotalInclTax); $total->setBaseSubtotalTotalInclTax($baseSubtotalInclTax); $total->setBaseSubtotalInclTax($baseSubtotalInclTax); - $shippingAssignment->getShipping()->getAddress()->setBaseSubtotalTotalInclTax($baseSubtotalInclTax); - $shippingAssignment->getShipping()->getAddress()->setBaseTaxAmount($baseTax); + $address = $shippingAssignment->getShipping()->getAddress(); + $address->setBaseTaxAmount($baseTax); + $address->setBaseSubtotalTotalInclTax($baseSubtotalInclTax); + $address->setSubtotal($total->getSubtotal()); + $address->setBaseSubtotal($total->getBaseSubtotal()); return $this; } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php index ae1f475d43b71..5a2351f7a1660 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php @@ -67,110 +67,110 @@ protected function getCustomerById($id) * @magentoDataFixture Magento/Catalog/_files/products.php * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION * @dataProvider collectUnitBasedDataProvider + * @param array $quoteItems + * @param array $expected + * @return void */ - public function testCollectUnitBased($expected) + public function testCollectUnitBased(array $quoteItems, array $expected): void { - $customerTaxClassId = $this->getCustomerTaxClassId(); - $fixtureCustomerId = 1; - /** @var \Magento\Customer\Model\Customer $customer */ - $customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load($fixtureCustomerId); - /** @var \Magento\Customer\Model\Group $customerGroup */ - $customerGroup = $this->objectManager->create( - \Magento\Customer\Model\Group::class - )->load( - 'custom_group', - 'customer_group_code' - ); - $customerGroup->setTaxClassId($customerTaxClassId)->save(); - $customer->setGroupId($customerGroup->getId())->save(); + $this->quote($quoteItems, $expected); + } + + public function collectUnitBasedDataProvider(): array + { + return [ + 'one_item' => [ + [ + [ + 'sku' => 'simple', + 'qty' => 2 + ], + ], + [ + [ + 'subtotal' => 20, + 'subtotal_incl_tax' => 21.5, + 'base_subtotal_total_incl_tax' => 21.5, + 'tax_amount' => 1.5, + 'discount_amount' => 0, + ], + [ + [ + 'tax_amount' => 1.5, + 'price' => 10, + 'price_incl_tax' => 10.75, + 'row_total' => 20, + 'row_total_incl_tax' => 21.5, + 'tax_percent' => 7.5, + ], + ], + ], + ], + ]; + } + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * @magentoDataFixture Magento/Tax/_files/tax_classes.php + * @magentoDataFixture Magento/Customer/_files/customer_group.php + * @magentoDataFixture Magento/Bundle/_files/product.php + * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION + * @dataProvider collectUnitBasedBundleProductDataProvider + * @param array $quoteItems + * @param array $expected + * @return void + */ + public function testCollectUnitBasedBundleProduct(array $quoteItems, array $expected): void + { $productTaxClassId = $this->getProductTaxClassId(); /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->productRepository->get('simple'); - $product->setTaxClassId($productTaxClassId)->save(); - - $quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId); - - /** @var \Magento\Quote\Model\Quote\Address $quoteShippingAddress */ - $quoteShippingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class); - $quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject); - $quantity = 2; - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->setStoreId( - 1 - )->setIsActive( - true - )->setIsMultiShipping( - false - )->assignCustomerWithAddressChange( - $this->getCustomerById($customer->getId()) - )->setShippingAddress( - $quoteShippingAddress - )->setBillingAddress( - $quoteShippingAddress - )->setCheckoutMethod( - $customer->getMode() - )->setPasswordHash( - $customer->encryptPassword($customer->getPassword()) - )->addProduct( - $product->load($product->getId()), - $quantity - ); - $address = $quote->getShippingAddress(); - /** @var \Magento\Quote\Model\ShippingAssignment $shippingAssignment */ - $shippingAssignment = $this->objectManager->create(\Magento\Quote\Model\ShippingAssignment::class); - $shipping = $this->objectManager->create(\Magento\Quote\Model\Shipping::class); - $shipping->setAddress($address); - $shippingAssignment->setShipping($shipping); - $shippingAssignment->setItems($address->getAllItems()); - /** @var \Magento\Quote\Model\Quote\Address\Total $total */ - $total = $this->objectManager->create(\Magento\Quote\Model\Quote\Address\Total::class); - /** @var \Magento\Quote\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */ - $addressSubtotalCollector = $this->objectManager->create( - \Magento\Quote\Model\Quote\Address\Total\Subtotal::class - ); - $addressSubtotalCollector->collect($quote, $shippingAssignment, $total); - - /** @var \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subtotalCollector */ - $subtotalCollector = $this->objectManager->create(\Magento\Tax\Model\Sales\Total\Quote\Subtotal::class); - $subtotalCollector->collect($quote, $shippingAssignment, $total); - - $this->assertEquals($expected['subtotal'], $total->getSubtotal()); - $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax()); - $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getBaseSubtotalTotalInclTax()); - $this->assertEquals($expected['discount_amount'], $total->getDiscountAmount()); - $items = $address->getAllItems(); - /** @var \Magento\Quote\Model\Quote\Address\Item $item */ - $item = $items[0]; - $this->assertEquals($expected['items'][0]['price'], $item->getPrice()); - $this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax()); - $this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal()); - $this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax()); - $this->assertEquals($expected['items'][0]['tax_percent'], $item->getTaxPercent()); + $childProduct = $this->productRepository->get('simple'); + $childProduct->setTaxClassId($productTaxClassId)->save(); + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->get('bundle-product'); + $product->setTaxClassId($productTaxClassId) + ->setPriceType(\Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD) + ->save(); + $quoteItems[0]['product'] = $product; + $this->quote($quoteItems, $expected); } - public function collectUnitBasedDataProvider() + public function collectUnitBasedBundleProductDataProvider(): array { return [ 'one_item' => [ [ - 'subtotal' => 20, - 'tax_amount' => 1.5, - 'discount_amount' => 0, - 'items' => [ + [ + 'sku' => 'bundle-product', + 'qty' => 2 + ], + ], + [ + [ + 'subtotal' => 20, + 'subtotal_incl_tax' => 21.5, + 'base_subtotal_total_incl_tax' => 21.5, + 'tax_amount' => 1.5, + 'discount_amount' => 0, + ], + [ [ 'tax_amount' => 1.5, 'price' => 10, 'price_incl_tax' => 10.75, 'row_total' => 20, 'row_total_incl_tax' => 21.5, - 'taxable_amount' => 10, - 'code' => 'simple', - 'type' => 'product', - 'tax_percent' => 7.5, + 'tax_percent' => null, ], + [ + 'tax_amount' => 1.5, + 'price' => 10, + 'price_incl_tax' => 10.75, + 'row_total' => 20, + 'row_total_incl_tax' => 21.5, + 'tax_percent' => 7.5, + ] ], ], ], @@ -178,16 +178,96 @@ public function collectUnitBasedDataProvider() } /** - * @magentoDbIsolation disabled + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @magentoConfigFixture current_store tax/calculation/cross_border_trade_enabled 1 * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/Customer/_files/customer_address.php * @magentoDataFixture Magento/Tax/_files/tax_classes.php * @magentoDataFixture Magento/Customer/_files/customer_group.php - * @magentoDataFixture Magento/Bundle/_files/product.php + * @magentoDataFixture Magento/Catalog/_files/products.php * @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION - * @dataProvider collectUnitBasedDataProvider + * @magentoConfigFixture current_store tax/calculation/price_includes_tax 1 + * @dataProvider collectUnitBasedPriceIncludesTaxDataProvider + * @param array $quoteItems + * @param array $expected + */ + public function testCollectUnitBasedPriceIncludesTax(array $quoteItems, array $expected): void + { + $this->quote($quoteItems, $expected); + } + + /** + * @return array + */ + public function collectUnitBasedPriceIncludesTaxDataProvider(): array + { + return [ + [ + [ + [ + 'sku' => 'simple', + 'qty' => 1 + ], + ], + [ + [ + 'subtotal' => 9.3, + 'subtotal_incl_tax' => 10, + 'base_subtotal_total_incl_tax' => 10, + 'tax_amount' => 0.7, + 'discount_amount' => 0, + ], + [ + [ + 'tax_amount' => 0.7, + 'price' => 9.3, + 'price_incl_tax' => 10, + 'row_total' => 9.3, + 'row_total_incl_tax' => 10, + 'tax_percent' => 7.5, + ], + ], + ], + ], + [ + [ + [ + 'sku' => 'simple', + 'qty' => 2 + ], + ], + [ + [ + 'subtotal' => 18.6, + 'subtotal_incl_tax' => 20, + 'base_subtotal_total_incl_tax' => 20, + 'tax_amount' => 1.4, + 'discount_amount' => 0, + ], + [ + [ + 'tax_amount' => 1.4, + 'price' => 9.3, + 'price_incl_tax' => 10, + 'row_total' => 18.6, + 'row_total_incl_tax' => 20, + 'tax_percent' => 7.5, + ], + ], + ], + ], + ]; + } + + /** + * Create quote and assert totals values + * + * @param array $quoteItems + * @param array $expected + * @return void */ - public function testCollectUnitBasedBundleProduct($expected) + private function quote(array $quoteItems, array $expected): void { $customerTaxClassId = $this->getCustomerTaxClassId(); $fixtureCustomerId = 1; @@ -202,23 +282,14 @@ public function testCollectUnitBasedBundleProduct($expected) ); $customerGroup->setTaxClassId($customerTaxClassId)->save(); $customer->setGroupId($customerGroup->getId())->save(); - $productTaxClassId = $this->getProductTaxClassId(); - /** @var \Magento\Catalog\Model\Product $product */ - $childProduct = $this->productRepository->get('simple'); - $childProduct->setTaxClassId($productTaxClassId)->save(); - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->productRepository->get('bundle-product'); - $product->setTaxClassId($productTaxClassId) - ->setPriceType(\Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD) - ->save(); + $quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId); /** @var \Magento\Quote\Model\Quote\Address $quoteShippingAddress */ $quoteShippingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class); $quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject); - $quantity = 2; /** @var \Magento\Quote\Model\Quote $quote */ $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); @@ -238,17 +309,25 @@ public function testCollectUnitBasedBundleProduct($expected) $customer->getMode() )->setPasswordHash( $customer->encryptPassword($customer->getPassword()) - )->addProduct( - $product->load($product->getId()), - $quantity ); + + foreach ($quoteItems as $quoteItem) { + $product = $quoteItem['product'] ?? null; + if ($product === null) { + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->get($quoteItem['sku'] ?? 'simple'); + $product->setTaxClassId($productTaxClassId)->save(); + } + $quote->addProduct($product, $quoteItem['qty']); + } + $address = $quote->getShippingAddress(); /** @var \Magento\Quote\Model\ShippingAssignment $shippingAssignment */ $shippingAssignment = $this->objectManager->create(\Magento\Quote\Model\ShippingAssignment::class); $shipping = $this->objectManager->create(\Magento\Quote\Model\Shipping::class); $shipping->setAddress($address); $shippingAssignment->setShipping($shipping); - $shippingAssignment->setItems($quote->getAllItems()); + $shippingAssignment->setItems($address->getAllItems()); /** @var \Magento\Quote\Model\Quote\Address\Total $total */ $total = $this->objectManager->create(\Magento\Quote\Model\Quote\Address\Total::class); /** @var \Magento\Quote\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */ @@ -261,16 +340,20 @@ public function testCollectUnitBasedBundleProduct($expected) $subtotalCollector = $this->objectManager->create(\Magento\Tax\Model\Sales\Total\Quote\Subtotal::class); $subtotalCollector->collect($quote, $shippingAssignment, $total); - $this->assertEquals($expected['subtotal'], $total->getSubtotal()); - $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax()); - $this->assertEquals($expected['discount_amount'], $total->getDiscountAmount()); - $items = $address->getAllItems(); - /** @var \Magento\Quote\Model\Quote\Address\Item $item */ - $item = $items[0]; - $this->assertEquals($expected['items'][0]['price'], $item->getPrice()); - $this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax()); - $this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal()); - $this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax()); + $this->assertEquals($address->getSubtotal(), $total->getSubtotal()); + $this->assertEquals($address->getBaseSubtotal(), $total->getBaseSubtotal()); + $this->assertEquals($address->getBaseSubtotalTotalInclTax(), $total->getBaseSubtotalTotalInclTax()); + + $this->assertEquals($expected[0], $total->toArray(array_keys($expected[0]))); + $actualAddressItemsData = []; + if ($expected[1]) { + $keys = array_keys($expected[1][0]); + /** @var \Magento\Quote\Model\Quote\Address\Item $addressItem */ + foreach ($address->getAllItems() as $addressItem) { + $actualAddressItemsData[] = array_intersect_key($addressItem->toArray($keys), array_flip($keys)); + } + } + $this->assertEquals($expected[1], $actualAddressItemsData); } /** From d2bb11cd75513bd7fa121bd963ec86f4b653921b Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 29 Jan 2020 17:22:03 +0200 Subject: [PATCH 354/666] use objectmanager helper --- .../Unit/Observer/CheckoutCartAddProductObserverTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php index 25c3b62697e5d..ad7b9fed3436e 100644 --- a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php +++ b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php @@ -10,6 +10,7 @@ use Magento\Framework\Event; use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Quote\Model\Quote\Item as QuoteItem; use Magento\Reports\Model\Event as ReportsEventModel; use Magento\Reports\Model\ReportStatus; @@ -74,6 +75,14 @@ protected function setUp() $this->eventSaverMock, $this->reportStatusMock ); + $objectManager = new ObjectManager($this); + $this->observer = $objectManager->getObject( + CheckoutCartAddProductObserver::class, + [ + 'eventSaver' => $this->eventSaverMock, + 'reportStatus' => $this->reportStatusMock + ] + ); } /** From c81e72820847fe4a0caa1c7cc259052b33fb3d93 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 29 Jan 2020 17:23:38 +0200 Subject: [PATCH 355/666] remove typo --- .../Test/Unit/Observer/CheckoutCartAddProductObserverTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php index ad7b9fed3436e..02bdbdf794ac6 100644 --- a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php +++ b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php @@ -71,10 +71,6 @@ protected function setUp() ->setMethods(['getItem']) ->getMock(); - $this->observer = new CheckoutCartAddProductObserver( - $this->eventSaverMock, - $this->reportStatusMock - ); $objectManager = new ObjectManager($this); $this->observer = $objectManager->getObject( CheckoutCartAddProductObserver::class, From 25fd9259e72bc484f5899aa4edf3de120b66db0c Mon Sep 17 00:00:00 2001 From: Alexander Steshuk <grp-engcom-vendorworker-Kilo@adobe.com> Date: Wed, 29 Jan 2020 17:30:11 +0200 Subject: [PATCH 356/666] magento/magento2#26533: Unit test fix --- .../Unit/Module/Di/Code/Scanner/PhpScannerTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php index 46d45770055b0..3aea4166df838 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/PhpScannerTest.php @@ -7,6 +7,12 @@ namespace Magento\Setup\Test\Unit\Module\Di\Code\Scanner; +require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Helper/Test.php'; +require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/ElementFactory.php'; +require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/DoubleColon.php'; +require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Api/Data/SomeInterface.php'; +require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php'; + use Magento\Framework\Reflection\TypeProcessor; use Magento\Setup\Module\Di\Code\Scanner\PhpScanner; use Magento\Setup\Module\Di\Compiler\Log\Log; @@ -38,12 +44,6 @@ protected function setUp() public function testCollectEntities() { - require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Helper/Test.php'; - require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/ElementFactory.php'; - require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/DoubleColon.php'; - require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Api/Data/SomeInterface.php'; - require_once __DIR__ . '/../../_files/app/code/Magento/SomeModule/Model/StubWithAnonymousClass.php'; - $testFiles = [ $this->testDir . '/app/code/Magento/SomeModule/Helper/Test.php', $this->testDir . '/app/code/Magento/SomeModule/Model/DoubleColon.php', From 764f8c78d6d9257f943ade27f5a16822ecf70faf Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 29 Jan 2020 17:51:42 +0200 Subject: [PATCH 357/666] Cover unit test --- .../Magento/Store/Test/Unit/Controller/Store/RedirectTest.php | 4 ---- 1 file changed, 4 deletions(-) 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 41ff3de1942af..4408c45d6a640 100755 --- a/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php +++ b/app/code/Magento/Store/Test/Unit/Controller/Store/RedirectTest.php @@ -194,10 +194,6 @@ public function testRedirect(string $defaultStoreViewCode, string $storeCode): v ->expects($this->once()) ->method('getCode') ->willReturn($defaultStoreViewCode); - $this->sidResolverMock - ->expects($this->once()) - ->method('getUseSessionInUrl') - ->willReturn(false); $this->hashGeneratorMock ->expects($this->once()) ->method('generateHash') From 41b1cd54488dd6709124d618f1c570e9d0eab51a Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Wed, 29 Jan 2020 10:05:55 -0600 Subject: [PATCH 358/666] ECP-261: Offload Catalog Image Resizing from Magento --- .../Magento/Catalog/Block/Rss/Category.php | 4 +- .../Catalog/Block/Rss/Product/NewProducts.php | 28 +- .../Catalog/Block/Rss/Product/Special.php | 15 +- .../Adminhtml/Product/Gallery/Upload.php | 2 +- app/code/Magento/Catalog/Helper/Image.php | 33 +- .../Model/Config/CatalogMediaConfig.php | 50 ++ .../Source/Web/CatalogMediaUrlFormat.php | 30 ++ .../Catalog/Model/View/Asset/Image.php | 90 +++- .../Observer/ImageResizeAfterProductSave.php | 21 +- .../Helper/Form/Gallery/ContentTest.php | 442 ------------------ .../Test/Unit/Model/ImageUploaderTest.php | 154 ------ .../Model/View/Asset/Image/ContextTest.php | 76 --- .../Test/Unit/Model/View/Asset/ImageTest.php | 213 --------- .../Product/Listing/Collector/ImageTest.php | 13 +- .../Component/Listing/Columns/Thumbnail.php | 12 +- .../Product/Form/Modifier/Related.php | 6 +- .../Product/Listing/Collector/Image.php | 16 +- .../Magento/Catalog/etc/adminhtml/system.xml | 7 + app/code/Magento/Catalog/etc/config.xml | 5 + .../Checkout/CustomerData/DefaultItem.php | 8 +- .../Checkout/Model/DefaultConfigProvider.php | 2 +- .../Console/Command/ImagesResizeCommand.php | 5 +- .../HeaderProvider/UpgradeInsecureTest.php | 2 +- .../Wishlist/CustomerData/Wishlist.php | 27 +- .../Test/Unit/CustomerData/WishlistTest.php | 6 - .../Block/Product/View/GalleryTest.php | 102 ++++ .../Service/PaymentFailuresServiceTest.php | 2 +- .../ResourceModel/Catalog/ProductTest.php | 2 + nginx.conf.sample | 25 + 29 files changed, 431 insertions(+), 967 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Config/CatalogMediaConfig.php create mode 100644 app/code/Magento/Catalog/Model/Config/Source/Web/CatalogMediaUrlFormat.php delete mode 100644 app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php delete mode 100644 app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php delete mode 100644 app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php delete mode 100644 app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php diff --git a/app/code/Magento/Catalog/Block/Rss/Category.php b/app/code/Magento/Catalog/Block/Rss/Category.php index 50967d2eb8dca..f149114f2eab8 100644 --- a/app/code/Magento/Catalog/Block/Rss/Category.php +++ b/app/code/Magento/Catalog/Block/Rss/Category.php @@ -10,9 +10,7 @@ use Magento\Framework\Exception\NoSuchEntityException; /** - * Class Category - * - * @package Magento\Catalog\Block\Rss + * Category feed block * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ diff --git a/app/code/Magento/Catalog/Block/Rss/Product/NewProducts.php b/app/code/Magento/Catalog/Block/Rss/Product/NewProducts.php index 20c4bef0845d6..9ade8b198656c 100644 --- a/app/code/Magento/Catalog/Block/Rss/Product/NewProducts.php +++ b/app/code/Magento/Catalog/Block/Rss/Product/NewProducts.php @@ -8,8 +8,7 @@ use Magento\Framework\App\Rss\DataProviderInterface; /** - * Class NewProducts - * @package Magento\Catalog\Block\Rss\Product + * New products feed block */ class NewProducts extends \Magento\Framework\View\Element\AbstractBlock implements DataProviderInterface { @@ -55,6 +54,8 @@ public function __construct( } /** + * Init + * * @return void */ protected function _construct() @@ -64,7 +65,7 @@ protected function _construct() } /** - * {@inheritdoc} + * @inheritdoc */ public function isAllowed() { @@ -72,7 +73,7 @@ public function isAllowed() } /** - * {@inheritdoc} + * @inheritdoc */ public function getRssData() { @@ -97,10 +98,13 @@ public function getRssData() $item->setAllowedInRss(true); $item->setAllowedPriceInRss(true); - $this->_eventManager->dispatch('rss_catalog_new_xml_callback', [ - 'row' => $item->getData(), - 'product' => $item - ]); + $this->_eventManager->dispatch( + 'rss_catalog_new_xml_callback', + [ + 'row' => $item->getData(), + 'product' => $item + ] + ); if (!$item->getAllowedInRss()) { continue; @@ -132,6 +136,8 @@ public function getRssData() } /** + * Get store id + * * @return int */ protected function getStoreId() @@ -177,7 +183,7 @@ protected function renderPriceHtml(\Magento\Catalog\Model\Product $product) } /** - * {@inheritdoc} + * @inheritdoc */ public function getCacheLifetime() { @@ -185,6 +191,8 @@ public function getCacheLifetime() } /** + * Get feeds + * * @return array */ public function getFeeds() @@ -199,7 +207,7 @@ public function getFeeds() } /** - * {@inheritdoc} + * @inheritdoc */ public function isAuthRequired() { diff --git a/app/code/Magento/Catalog/Block/Rss/Product/Special.php b/app/code/Magento/Catalog/Block/Rss/Product/Special.php index a9107f14cc5e4..5e459413bb5a2 100644 --- a/app/code/Magento/Catalog/Block/Rss/Product/Special.php +++ b/app/code/Magento/Catalog/Block/Rss/Product/Special.php @@ -9,8 +9,7 @@ use Magento\Framework\App\Rss\DataProviderInterface; /** - * Class Special - * @package Magento\Catalog\Block\Rss\Product + * Special products feed block * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Special extends \Magento\Framework\View\Element\AbstractBlock implements DataProviderInterface @@ -98,6 +97,8 @@ public function __construct( } /** + * Init + * * @return void */ protected function _construct() @@ -107,6 +108,8 @@ protected function _construct() } /** + * Get RSS data + * * @return array */ public function getRssData() @@ -156,6 +159,8 @@ public function getRssData() } /** + * Get entry data + * * @param \Magento\Catalog\Model\Product $item * @return array */ @@ -245,7 +250,7 @@ public function isAllowed() } /** - * {@inheritdoc} + * @inheritdoc */ public function getCacheLifetime() { @@ -253,6 +258,8 @@ public function getCacheLifetime() } /** + * Get feeds + * * @return array */ public function getFeeds() @@ -266,7 +273,7 @@ public function getFeeds() } /** - * {@inheritdoc} + * @inheritdoc */ public function isAuthRequired() { diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php index d43b313c43b3e..3e7cc3ee962b9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php @@ -11,7 +11,7 @@ use Magento\Framework\Exception\LocalizedException; /** - * Class Upload + * Upload product image action controller */ class Upload extends \Magento\Backend\App\Action implements HttpPostActionInterface { diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index 110b798df9df9..191f5eee1b5e1 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -5,7 +5,11 @@ */ namespace Magento\Catalog\Helper; +use Magento\Catalog\Model\Config\CatalogMediaConfig; +use Magento\Catalog\Model\View\Asset\PlaceholderFactory; use Magento\Framework\App\Helper\AbstractHelper; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\View\Element\Block\ArgumentInterface; /** @@ -129,31 +133,39 @@ class Image extends AbstractHelper implements ArgumentInterface protected $attributes = []; /** - * @var \Magento\Catalog\Model\View\Asset\PlaceholderFactory + * @var PlaceholderFactory */ private $viewAssetPlaceholderFactory; + /** + * @var CatalogMediaConfig + */ + private $mediaConfig; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Catalog\Model\Product\ImageFactory $productImageFactory * @param \Magento\Framework\View\Asset\Repository $assetRepo * @param \Magento\Framework\View\ConfigInterface $viewConfig - * @param \Magento\Catalog\Model\View\Asset\PlaceholderFactory $placeholderFactory + * @param PlaceholderFactory $placeholderFactory + * @param CatalogMediaConfig $mediaConfig */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Catalog\Model\Product\ImageFactory $productImageFactory, \Magento\Framework\View\Asset\Repository $assetRepo, \Magento\Framework\View\ConfigInterface $viewConfig, - \Magento\Catalog\Model\View\Asset\PlaceholderFactory $placeholderFactory = null + PlaceholderFactory $placeholderFactory = null, + CatalogMediaConfig $mediaConfig = null ) { $this->_productImageFactory = $productImageFactory; parent::__construct($context); $this->_assetRepo = $assetRepo; $this->viewConfig = $viewConfig; $this->viewAssetPlaceholderFactory = $placeholderFactory - ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Model\View\Asset\PlaceholderFactory::class); + ?: ObjectManager::getInstance() + ->get(PlaceholderFactory::class); + $this->mediaConfig = $mediaConfig ?: ObjectManager::getInstance()->get(CatalogMediaConfig::class); } /** @@ -526,7 +538,16 @@ protected function isScheduledActionsAllowed() public function getUrl() { try { - $this->applyScheduledActions(); + switch ($this->mediaConfig->getMediaUrlFormat()) { + case CatalogMediaConfig::IMAGE_OPTIMIZATION_PARAMETERS: + $this->initBaseFile(); + break; + case CatalogMediaConfig::HASH: + $this->applyScheduledActions(); + break; + default: + throw new LocalizedException(__("The specified Catalog media URL format is not supported.")); + } return $this->_getModel()->getUrl(); } catch (\Exception $e) { return $this->getDefaultPlaceholderUrl(); diff --git a/app/code/Magento/Catalog/Model/Config/CatalogMediaConfig.php b/app/code/Magento/Catalog/Model/Config/CatalogMediaConfig.php new file mode 100644 index 0000000000000..9e5394f0d6585 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Config/CatalogMediaConfig.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\Config; + +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Config for catalog media + */ +class CatalogMediaConfig +{ + private const XML_PATH_CATALOG_MEDIA_URL_FORMAT = 'web/url/catalog_media_url_format'; + + const IMAGE_OPTIMIZATION_PARAMETERS = 'image_optimization_parameters'; + const HASH = 'hash'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Constructor + * + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct(ScopeConfigInterface $scopeConfig) + { + $this->scopeConfig = $scopeConfig; + } + + /** + * Get media URL format for catalog images + * + * @param string $scopeType + * @param null|int|string $scopeCode + * @return string + */ + public function getMediaUrlFormat($scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) + { + return $this->scopeConfig->getValue( + CatalogMediaConfig::XML_PATH_CATALOG_MEDIA_URL_FORMAT, + $scopeType, + $scopeCode + ); + } +} diff --git a/app/code/Magento/Catalog/Model/Config/Source/Web/CatalogMediaUrlFormat.php b/app/code/Magento/Catalog/Model/Config/Source/Web/CatalogMediaUrlFormat.php new file mode 100644 index 0000000000000..f24044fc92c95 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Config/Source/Web/CatalogMediaUrlFormat.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\Config\Source\Web; + +use Magento\Catalog\Model\Config\CatalogMediaConfig; + +/** + * Option provider for catalog media URL format system setting. + */ +class CatalogMediaUrlFormat implements \Magento\Framework\Data\OptionSourceInterface +{ + /** + * Get a list of supported catalog media URL formats. + * + * @codeCoverageIgnore + */ + public function toOptionArray() + { + return [ + [ + 'value' => CatalogMediaConfig::IMAGE_OPTIMIZATION_PARAMETERS, + 'label' => __('Image optimization based on query parameters') + ], + ['value' => CatalogMediaConfig::HASH, 'label' => __('Unique hash per image variant (Legacy mode)')] + ]; + } +} diff --git a/app/code/Magento/Catalog/Model/View/Asset/Image.php b/app/code/Magento/Catalog/Model/View/Asset/Image.php index c547ec612bb94..da1009ab1125c 100644 --- a/app/code/Magento/Catalog/Model/View/Asset/Image.php +++ b/app/code/Magento/Catalog/Model/View/Asset/Image.php @@ -6,11 +6,16 @@ namespace Magento\Catalog\Model\View\Asset; +use Magento\Catalog\Model\Config\CatalogMediaConfig; use Magento\Catalog\Model\Product\Media\ConfigInterface; use Magento\Framework\Encryption\Encryptor; use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\View\Asset\ContextInterface; use Magento\Framework\View\Asset\LocalInterface; +use Magento\Catalog\Helper\Image as ImageHelper; +use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\StoreManagerInterface; /** * A locally available image file asset that can be referred with a file path @@ -58,6 +63,21 @@ class Image implements LocalInterface */ private $encryptor; + /** + * @var ImageHelper + */ + private $imageHelper; + + /** + * @var CatalogMediaConfig + */ + private $catalogMediaConfig; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * Image constructor. * @@ -66,13 +86,19 @@ class Image implements LocalInterface * @param EncryptorInterface $encryptor * @param string $filePath * @param array $miscParams + * @param ImageHelper $imageHelper + * @param CatalogMediaConfig $catalogMediaConfig + * @param StoreManagerInterface $storeManager */ public function __construct( ConfigInterface $mediaConfig, ContextInterface $context, EncryptorInterface $encryptor, $filePath, - array $miscParams + array $miscParams, + ImageHelper $imageHelper = null, + CatalogMediaConfig $catalogMediaConfig = null, + StoreManagerInterface $storeManager = null ) { if (isset($miscParams['image_type'])) { $this->sourceContentType = $miscParams['image_type']; @@ -85,14 +111,72 @@ public function __construct( $this->filePath = $filePath; $this->miscParams = $miscParams; $this->encryptor = $encryptor; + $this->imageHelper = $imageHelper ?: ObjectManager::getInstance()->get(ImageHelper::class); + $this->catalogMediaConfig = $catalogMediaConfig ?: ObjectManager::getInstance()->get(CatalogMediaConfig::class); + $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); } /** - * @inheritdoc + * Get catalog image URL. + * + * @return string + * @throws LocalizedException */ public function getUrl() { - return $this->context->getBaseUrl() . DIRECTORY_SEPARATOR . $this->getImageInfo(); + $mediaUrlFormat = $this->catalogMediaConfig->getMediaUrlFormat(); + switch ($mediaUrlFormat) { + case CatalogMediaConfig::IMAGE_OPTIMIZATION_PARAMETERS: + return $this->getUrlWithTransformationParameters(); + case CatalogMediaConfig::HASH: + return $this->context->getBaseUrl() . DIRECTORY_SEPARATOR . $this->getImageInfo(); + default: + throw new LocalizedException( + __("The specified Catalog media URL format '$mediaUrlFormat' is not supported.") + ); + } + } + + /** + * Get image URL with transformation parameters + * + * @return string + */ + private function getUrlWithTransformationParameters() + { + return $this->getOriginalImageUrl() . '?' . http_build_query($this->getImageTransformationParameters()); + } + + /** + * The list of parameters to be used during image transformations (e.g. resizing or applying watermarks). + * + * This method can be used as an extension point. + * + * @return string[] + */ + public function getImageTransformationParameters() + { + return [ + 'width' => $this->miscParams['image_width'], + 'height' => $this->miscParams['image_height'], + 'store' => $this->storeManager->getStore()->getCode(), + 'image-type' => $this->sourceContentType + ]; + } + + /** + * Get URL to the original version of the product image. + * + * @return string + */ + private function getOriginalImageUrl() + { + $originalImageFile = $this->getSourceFile(); + if (!$originalImageFile) { + return $this->imageHelper->getDefaultPlaceholderUrl(); + } else { + return $this->context->getBaseUrl() . $this->getFilePath(); + } } /** diff --git a/app/code/Magento/Catalog/Observer/ImageResizeAfterProductSave.php b/app/code/Magento/Catalog/Observer/ImageResizeAfterProductSave.php index 91d2868afab8c..54b655a217a08 100644 --- a/app/code/Magento/Catalog/Observer/ImageResizeAfterProductSave.php +++ b/app/code/Magento/Catalog/Observer/ImageResizeAfterProductSave.php @@ -10,7 +10,11 @@ use Magento\Framework\Event\ObserverInterface; use Magento\Framework\App\State; use Magento\MediaStorage\Service\ImageResize; +use Magento\Catalog\Model\Config\CatalogMediaConfig; +/** + * Resize product images after the product is saved + */ class ImageResizeAfterProductSave implements ObserverInterface { /** @@ -23,17 +27,26 @@ class ImageResizeAfterProductSave implements ObserverInterface */ private $state; + /** + * @var CatalogMediaConfig + */ + private $catalogMediaConfig; + /** * Product constructor. + * * @param ImageResize $imageResize * @param State $state + * @param CatalogMediaConfig $catalogMediaConfig */ public function __construct( ImageResize $imageResize, - State $state + State $state, + CatalogMediaConfig $catalogMediaConfig ) { $this->imageResize = $imageResize; $this->state = $state; + $this->catalogMediaConfig = $catalogMediaConfig; } /** @@ -44,6 +57,12 @@ public function __construct( */ public function execute(\Magento\Framework\Event\Observer $observer) { + $catalogMediaUrlFormat = $this->catalogMediaConfig->getMediaUrlFormat(); + if ($catalogMediaUrlFormat == CatalogMediaConfig::IMAGE_OPTIMIZATION_PARAMETERS) { + // Skip image resizing on the Magento side when it is offloaded to a web server or CDN + return; + } + /** @var $product \Magento\Catalog\Model\Product */ $product = $observer->getEvent()->getProduct(); diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php deleted file mode 100644 index 9a2199859a1df..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php +++ /dev/null @@ -1,442 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Catalog\Test\Unit\Block\Adminhtml\Product\Helper\Form\Gallery; - -use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery\Content; -use Magento\Catalog\Model\Entity\Attribute; -use Magento\Catalog\Model\Product; -use Magento\Framework\Phrase; -use Magento\MediaStorage\Helper\File\Storage\Database; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class ContentTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject - */ - protected $fileSystemMock; - - /** - * @var \Magento\Framework\Filesystem\Directory\Read|\PHPUnit_Framework_MockObject_MockObject - */ - protected $readMock; - - /** - * @var Content|\PHPUnit_Framework_MockObject_MockObject - */ - protected $content; - - /** - * @var \Magento\Catalog\Model\Product\Media\Config|\PHPUnit_Framework_MockObject_MockObject - */ - protected $mediaConfigMock; - - /** - * @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $jsonEncoderMock; - - /** - * @var \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery|\PHPUnit_Framework_MockObject_MockObject - */ - protected $galleryMock; - - /** - * @var \Magento\Catalog\Helper\Image|\PHPUnit_Framework_MockObject_MockObject - */ - protected $imageHelper; - - /** - * @var \Magento\MediaStorage\Helper\File\Storage\Database|\PHPUnit_Framework_MockObject_MockObject - */ - protected $databaseMock; - - /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager - */ - protected $objectManager; - - public function setUp() - { - $this->fileSystemMock = $this->createPartialMock( - \Magento\Framework\Filesystem::class, - ['stat', 'getDirectoryRead'] - ); - $this->readMock = $this->createMock(\Magento\Framework\Filesystem\Directory\ReadInterface::class); - $this->galleryMock = $this->createMock(\Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery::class); - $this->mediaConfigMock = $this->createPartialMock( - \Magento\Catalog\Model\Product\Media\Config::class, - ['getMediaUrl', 'getMediaPath'] - ); - $this->jsonEncoderMock = $this->getMockBuilder(\Magento\Framework\Json\EncoderInterface::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->databaseMock = $this->getMockBuilder(Database::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->content = $this->objectManager->getObject( - \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery\Content::class, - [ - 'mediaConfig' => $this->mediaConfigMock, - 'jsonEncoder' => $this->jsonEncoderMock, - 'filesystem' => $this->fileSystemMock, - 'fileStorageDatabase' => $this->databaseMock - ] - ); - } - - public function testGetImagesJson() - { - $url = [ - ['file_1.jpg', 'url_to_the_image/image_1.jpg'], - ['file_2.jpg', 'url_to_the_image/image_2.jpg'] - ]; - $mediaPath = [ - ['file_1.jpg', 'catalog/product/image_1.jpg'], - ['file_2.jpg', 'catalog/product/image_2.jpg'] - ]; - - $sizeMap = [ - ['catalog/product/image_1.jpg', ['size' => 399659]], - ['catalog/product/image_2.jpg', ['size' => 879394]] - ]; - - $imagesResult = [ - [ - 'value_id' => '2', - 'file' => 'file_2.jpg', - 'media_type' => 'image', - 'position' => '0', - 'url' => 'url_to_the_image/image_2.jpg', - 'size' => 879394 - ], - [ - 'value_id' => '1', - 'file' => 'file_1.jpg', - 'media_type' => 'image', - 'position' => '1', - 'url' => 'url_to_the_image/image_1.jpg', - 'size' => 399659 - ] - ]; - - $images = [ - 'images' => [ - [ - 'value_id' => '1', - 'file' => 'file_1.jpg', - 'media_type' => 'image', - 'position' => '1' - ] , - [ - 'value_id' => '2', - 'file' => 'file_2.jpg', - 'media_type' => 'image', - 'position' => '0' - ] - ] - ]; - - $this->content->setElement($this->galleryMock); - $this->galleryMock->expects($this->once())->method('getImages')->willReturn($images); - $this->fileSystemMock->expects($this->once())->method('getDirectoryRead')->willReturn($this->readMock); - - $this->mediaConfigMock->expects($this->any())->method('getMediaUrl')->willReturnMap($url); - $this->mediaConfigMock->expects($this->any())->method('getMediaPath')->willReturnMap($mediaPath); - $this->readMock->expects($this->any())->method('stat')->willReturnMap($sizeMap); - $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturnCallback('json_encode'); - - $this->readMock->expects($this->any()) - ->method('isFile') - ->will($this->returnValue(true)); - $this->databaseMock->expects($this->any()) - ->method('checkDbUsage') - ->will($this->returnValue(false)); - - $this->assertSame(json_encode($imagesResult), $this->content->getImagesJson()); - } - - public function testGetImagesJsonWithoutImages() - { - $this->content->setElement($this->galleryMock); - $this->galleryMock->expects($this->once())->method('getImages')->willReturn(null); - - $this->assertSame('[]', $this->content->getImagesJson()); - } - - public function testGetImagesJsonWithException() - { - $this->imageHelper = $this->getMockBuilder(\Magento\Catalog\Helper\Image::class) - ->disableOriginalConstructor() - ->setMethods(['getDefaultPlaceholderUrl']) - ->getMock(); - - $this->objectManager->setBackwardCompatibleProperty( - $this->content, - 'imageHelper', - $this->imageHelper - ); - - $placeholderUrl = 'url_to_the_placeholder/placeholder.jpg'; - - $imagesResult = [ - [ - 'value_id' => '2', - 'file' => 'file_2.jpg', - 'media_type' => 'image', - 'position' => '0', - 'url' => 'url_to_the_placeholder/placeholder.jpg', - 'size' => 0 - ], - [ - 'value_id' => '1', - 'file' => 'file_1.jpg', - 'media_type' => 'image', - 'position' => '1', - 'url' => 'url_to_the_placeholder/placeholder.jpg', - 'size' => 0 - ] - ]; - - $images = [ - 'images' => [ - [ - 'value_id' => '1', - 'file' => 'file_1.jpg', - 'media_type' => 'image', - 'position' => '1' - ], - [ - 'value_id' => '2', - 'file' => 'file_2.jpg', - 'media_type' => 'image', - 'position' => '0' - ] - ] - ]; - - $this->content->setElement($this->galleryMock); - $this->galleryMock->expects($this->once())->method('getImages')->willReturn($images); - $this->fileSystemMock->expects($this->any())->method('getDirectoryRead')->willReturn($this->readMock); - $this->mediaConfigMock->expects($this->any())->method('getMediaUrl'); - $this->mediaConfigMock->expects($this->any())->method('getMediaPath'); - - $this->readMock->expects($this->any()) - ->method('isFile') - ->will($this->returnValue(true)); - $this->databaseMock->expects($this->any()) - ->method('checkDbUsage') - ->will($this->returnValue(false)); - - $this->readMock->expects($this->any())->method('stat')->willReturnOnConsecutiveCalls( - $this->throwException( - new \Magento\Framework\Exception\FileSystemException(new Phrase('test')) - ), - $this->throwException( - new \Magento\Framework\Exception\FileSystemException(new Phrase('test')) - ) - ); - $this->imageHelper->expects($this->any())->method('getDefaultPlaceholderUrl')->willReturn($placeholderUrl); - $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturnCallback('json_encode'); - - $this->assertSame(json_encode($imagesResult), $this->content->getImagesJson()); - } - - /** - * Test GetImageTypes() will return value for given attribute from data persistor. - * - * @return void - */ - public function testGetImageTypesFromDataPersistor() - { - $attributeCode = 'thumbnail'; - $value = 'testImageValue'; - $scopeLabel = 'testScopeLabel'; - $label = 'testLabel'; - $name = 'testName'; - $expectedTypes = [ - $attributeCode => [ - 'code' => $attributeCode, - 'value' => $value, - 'label' => $label, - 'name' => $name, - ], - ]; - $product = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->getMock(); - $product->expects($this->once()) - ->method('getData') - ->with($this->identicalTo($attributeCode)) - ->willReturn(null); - $mediaAttribute = $this->getMediaAttribute($label, $attributeCode); - $product->expects($this->once()) - ->method('getMediaAttributes') - ->willReturn([$mediaAttribute]); - $this->galleryMock->expects($this->exactly(2)) - ->method('getDataObject') - ->willReturn($product); - $this->galleryMock->expects($this->once()) - ->method('getImageValue') - ->with($this->identicalTo($attributeCode)) - ->willReturn($value); - $this->galleryMock->expects($this->once()) - ->method('getScopeLabel') - ->with($this->identicalTo($mediaAttribute)) - ->willReturn($scopeLabel); - $this->galleryMock->expects($this->once()) - ->method('getAttributeFieldName') - ->with($this->identicalTo($mediaAttribute)) - ->willReturn($name); - $this->getImageTypesAssertions($attributeCode, $scopeLabel, $expectedTypes); - } - - /** - * Test GetImageTypes() will return value for given attribute from product. - * - * @return void - */ - public function testGetImageTypesFromProduct() - { - $attributeCode = 'thumbnail'; - $value = 'testImageValue'; - $scopeLabel = 'testScopeLabel'; - $label = 'testLabel'; - $name = 'testName'; - $expectedTypes = [ - $attributeCode => [ - 'code' => $attributeCode, - 'value' => $value, - 'label' => $label, - 'name' => $name, - ], - ]; - $product = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->getMock(); - $product->expects($this->once()) - ->method('getData') - ->with($this->identicalTo($attributeCode)) - ->willReturn($value); - $mediaAttribute = $this->getMediaAttribute($label, $attributeCode); - $product->expects($this->once()) - ->method('getMediaAttributes') - ->willReturn([$mediaAttribute]); - $this->galleryMock->expects($this->exactly(2)) - ->method('getDataObject') - ->willReturn($product); - $this->galleryMock->expects($this->never()) - ->method('getImageValue'); - $this->galleryMock->expects($this->once()) - ->method('getScopeLabel') - ->with($this->identicalTo($mediaAttribute)) - ->willReturn($scopeLabel); - $this->galleryMock->expects($this->once()) - ->method('getAttributeFieldName') - ->with($this->identicalTo($mediaAttribute)) - ->willReturn($name); - $this->getImageTypesAssertions($attributeCode, $scopeLabel, $expectedTypes); - } - - /** - * Perform assertions. - * - * @param string $attributeCode - * @param string $scopeLabel - * @param array $expectedTypes - * @return void - */ - private function getImageTypesAssertions(string $attributeCode, string $scopeLabel, array $expectedTypes) - { - $this->content->setElement($this->galleryMock); - $result = $this->content->getImageTypes(); - $scope = $result[$attributeCode]['scope']; - $this->assertSame($scopeLabel, $scope->getText()); - unset($result[$attributeCode]['scope']); - $this->assertSame($expectedTypes, $result); - } - - /** - * Get media attribute mock. - * - * @param string $label - * @param string $attributeCode - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function getMediaAttribute(string $label, string $attributeCode) - { - $frontend = $this->getMockBuilder(Product\Attribute\Frontend\Image::class) - ->disableOriginalConstructor() - ->getMock(); - $frontend->expects($this->once()) - ->method('getLabel') - ->willReturn($label); - $mediaAttribute = $this->getMockBuilder(Attribute::class) - ->disableOriginalConstructor() - ->getMock(); - $mediaAttribute->expects($this->any()) - ->method('getAttributeCode') - ->willReturn($attributeCode); - $mediaAttribute->expects($this->once()) - ->method('getFrontend') - ->willReturn($frontend); - - return $mediaAttribute; - } - - /** - * Test GetImagesJson() calls MediaStorage functions to obtain image from DB prior to stat call - * - * @return void - */ - public function testGetImagesJsonMediaStorageMode() - { - $images = [ - 'images' => [ - [ - 'value_id' => '0', - 'file' => 'file_1.jpg', - 'media_type' => 'image', - 'position' => '0' - ] - ] - ]; - - $mediaPath = [ - ['file_1.jpg', 'catalog/product/image_1.jpg'] - ]; - - $this->content->setElement($this->galleryMock); - - $this->galleryMock->expects($this->once()) - ->method('getImages') - ->willReturn($images); - $this->fileSystemMock->expects($this->once()) - ->method('getDirectoryRead') - ->willReturn($this->readMock); - $this->mediaConfigMock->expects($this->any()) - ->method('getMediaPath') - ->willReturnMap($mediaPath); - - $this->readMock->expects($this->any()) - ->method('isFile') - ->will($this->returnValue(false)); - $this->databaseMock->expects($this->any()) - ->method('checkDbUsage') - ->will($this->returnValue(true)); - - $this->databaseMock->expects($this->once()) - ->method('saveFileToFilesystem') - ->with('catalog/product/image_1.jpg'); - - $this->content->getImagesJson(); - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php deleted file mode 100644 index 6552e85440008..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Model/ImageUploaderTest.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Catalog\Test\Unit\Model; - -class ImageUploaderTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Catalog\Model\ImageUploader - */ - private $imageUploader; - - /** - * Core file storage database - * - * @var \Magento\MediaStorage\Helper\File\Storage\Database|\PHPUnit_Framework_MockObject_MockObject - */ - private $coreFileStorageDatabaseMock; - - /** - * Media directory object (writable). - * - * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject - */ - private $mediaDirectoryMock; - - /** - * Media directory object (writable). - * - * @var \Magento\Framework\Filesystem\Directory\WriteInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $mediaWriteDirectoryMock; - - /** - * Uploader factory - * - * @var \Magento\MediaStorage\Model\File\UploaderFactory|\PHPUnit_Framework_MockObject_MockObject - */ - private $uploaderFactoryMock; - - /** - * Store manager - * - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $storeManagerMock; - - /** - * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $loggerMock; - - /** - * Base tmp path - * - * @var string - */ - private $baseTmpPath; - - /** - * Base path - * - * @var string - */ - private $basePath; - - /** - * Allowed extensions - * - * @var array - */ - private $allowedExtensions; - - /** - * Allowed mime types - * - * @var array - */ - private $allowedMimeTypes; - - protected function setUp() - { - $this->coreFileStorageDatabaseMock = $this->createMock( - \Magento\MediaStorage\Helper\File\Storage\Database::class - ); - $this->mediaDirectoryMock = $this->createMock( - \Magento\Framework\Filesystem::class - ); - $this->mediaWriteDirectoryMock = $this->createMock( - \Magento\Framework\Filesystem\Directory\WriteInterface::class - ); - $this->mediaDirectoryMock->expects($this->any())->method('getDirectoryWrite')->willReturn( - $this->mediaWriteDirectoryMock - ); - $this->uploaderFactoryMock = $this->createMock( - \Magento\MediaStorage\Model\File\UploaderFactory::class - ); - $this->storeManagerMock = $this->createMock( - \Magento\Store\Model\StoreManagerInterface::class - ); - $this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class); - $this->baseTmpPath = 'base/tmp/'; - $this->basePath = 'base/real/'; - $this->allowedExtensions = ['.jpg']; - $this->allowedMimeTypes = ['image/jpg', 'image/jpeg', 'image/gif', 'image/png']; - - $this->imageUploader = - new \Magento\Catalog\Model\ImageUploader( - $this->coreFileStorageDatabaseMock, - $this->mediaDirectoryMock, - $this->uploaderFactoryMock, - $this->storeManagerMock, - $this->loggerMock, - $this->baseTmpPath, - $this->basePath, - $this->allowedExtensions, - $this->allowedMimeTypes - ); - } - - public function testSaveFileToTmpDir() - { - $fileId = 'file.jpg'; - $allowedMimeTypes = [ - 'image/jpg', - 'image/jpeg', - 'image/gif', - 'image/png', - ]; - /** @var \Magento\MediaStorage\Model\File\Uploader|\PHPUnit_Framework_MockObject_MockObject $uploader */ - $uploader = $this->createMock(\Magento\MediaStorage\Model\File\Uploader::class); - $this->uploaderFactoryMock->expects($this->once())->method('create')->willReturn($uploader); - $uploader->expects($this->once())->method('setAllowedExtensions')->with($this->allowedExtensions); - $uploader->expects($this->once())->method('setAllowRenameFiles')->with(true); - $this->mediaWriteDirectoryMock->expects($this->once())->method('getAbsolutePath')->with($this->baseTmpPath) - ->willReturn($this->basePath); - $uploader->expects($this->once())->method('save')->with($this->basePath) - ->willReturn(['tmp_name' => $this->baseTmpPath, 'file' => $fileId, 'path' => $this->basePath]); - $uploader->expects($this->atLeastOnce())->method('checkMimeType')->with($allowedMimeTypes)->willReturn(true); - $storeMock = $this->createPartialMock( - \Magento\Store\Model\Store::class, - ['getBaseUrl'] - ); - $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($storeMock); - $storeMock->expects($this->once())->method('getBaseUrl'); - $this->coreFileStorageDatabaseMock->expects($this->once())->method('saveFile'); - - $result = $this->imageUploader->saveFileToTmpDir($fileId); - - $this->assertArrayNotHasKey('path', $result); - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php deleted file mode 100644 index e73a2f30e2b10..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Catalog\Test\Unit\Model\View\Asset\Image; - -use Magento\Catalog\Model\Product\Media\ConfigInterface; -use Magento\Catalog\Model\View\Asset\Image\Context; -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Filesystem; -use Magento\Framework\Filesystem\Directory\WriteInterface; - -/** - * Class ContextTest - */ -class ContextTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var Context - */ - protected $model; - - /** - * @var WriteInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $mediaDirectory; - - /** - * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $mediaConfig; - - /** - * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filesystem; - - protected function setUp() - { - $this->mediaConfig = $this->getMockBuilder(ConfigInterface::class)->getMockForAbstractClass(); - $this->mediaConfig->expects($this->any())->method('getBaseMediaPath')->willReturn('catalog/product'); - $this->mediaDirectory = $this->getMockBuilder(WriteInterface::class)->getMockForAbstractClass(); - $this->mediaDirectory->expects($this->once())->method('create')->with('catalog/product'); - $this->filesystem = $this->getMockBuilder(Filesystem::class) - ->disableOriginalConstructor() - ->getMock(); - $this->filesystem->expects($this->once()) - ->method('getDirectoryWrite') - ->with(DirectoryList::MEDIA) - ->willReturn($this->mediaDirectory); - $this->model = new Context( - $this->mediaConfig, - $this->filesystem - ); - } - - public function testGetPath() - { - $path = '/var/www/html/magento2ce/pub/media/catalog/product'; - $this->mediaDirectory->expects($this->once()) - ->method('getAbsolutePath') - ->with('catalog/product') - ->willReturn($path); - - $this->assertEquals($path, $this->model->getPath()); - } - - public function testGetUrl() - { - $baseUrl = 'http://localhost/pub/media/catalog/product'; - $this->mediaConfig->expects($this->once())->method('getBaseMediaUrl')->willReturn($baseUrl); - - $this->assertEquals($baseUrl, $this->model->getBaseUrl()); - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php deleted file mode 100644 index 6832d5b3399d7..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Catalog\Test\Unit\Model\View\Asset; - -use Magento\Catalog\Model\Product\Media\ConfigInterface; -use Magento\Catalog\Model\View\Asset\Image; -use Magento\Framework\Encryption\Encryptor; -use Magento\Framework\Encryption\EncryptorInterface; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Framework\View\Asset\ContextInterface; -use Magento\Framework\View\Asset\Repository; - -/** - * Class ImageTest - */ -class ImageTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Catalog\Model\View\Asset\Image - */ - protected $model; - - /** - * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $mediaConfig; - - /** - * @var EncryptorInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $encryptor; - - /** - * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $context; - - /** - * @var Repository|\PHPUnit_Framework_MockObject_MockObject - */ - private $assetRepo; - - private $objectManager; - - protected function setUp() - { - $this->mediaConfig = $this->createMock(ConfigInterface::class); - $this->encryptor = $this->createMock(EncryptorInterface::class); - $this->context = $this->createMock(ContextInterface::class); - $this->assetRepo = $this->createMock(Repository::class); - $this->objectManager = new ObjectManager($this); - $this->model = $this->objectManager->getObject( - Image::class, - [ - 'mediaConfig' => $this->mediaConfig, - 'imageContext' => $this->context, - 'encryptor' => $this->encryptor, - 'filePath' => '/somefile.png', - 'assetRepo' => $this->assetRepo, - 'miscParams' => [ - 'image_width' => 100, - 'image_height' => 50, - 'constrain_only' => false, - 'keep_aspect_ratio' => false, - 'keep_frame' => true, - 'keep_transparency' => false, - 'background' => '255,255,255', - 'image_type' => 'image', //thumbnail,small_image,image,swatch_image,swatch_thumb - 'quality' => 80, - 'angle' => null - ] - ] - ); - } - - public function testModuleAndContentAndContentType() - { - $contentType = 'image'; - $this->assertEquals($contentType, $this->model->getContentType()); - $this->assertEquals($contentType, $this->model->getSourceContentType()); - $this->assertNull($this->model->getContent()); - $this->assertEquals('cache', $this->model->getModule()); - } - - public function testGetFilePath() - { - $this->assertEquals('/somefile.png', $this->model->getFilePath()); - } - - public function testGetSoureFile() - { - $this->mediaConfig->expects($this->once())->method('getBaseMediaPath')->willReturn('catalog/product'); - $this->assertEquals('catalog/product/somefile.png', $this->model->getSourceFile()); - } - - public function testGetContext() - { - $this->assertInstanceOf(ContextInterface::class, $this->model->getContext()); - } - - /** - * @param string $filePath - * @param array $miscParams - * @param string $readableParams - * @dataProvider getPathDataProvider - */ - public function testGetPath($filePath, $miscParams, $readableParams) - { - $imageModel = $this->objectManager->getObject( - Image::class, - [ - 'mediaConfig' => $this->mediaConfig, - 'context' => $this->context, - 'encryptor' => $this->encryptor, - 'filePath' => $filePath, - 'assetRepo' => $this->assetRepo, - 'miscParams' => $miscParams - ] - ); - $absolutePath = '/var/www/html/magento2ce/pub/media/catalog/product'; - $hashPath = 'somehash'; - $this->context->method('getPath')->willReturn($absolutePath); - $this->encryptor->expects(static::once()) - ->method('hash') - ->with($readableParams, $this->anything()) - ->willReturn($hashPath); - static::assertEquals( - $absolutePath . '/cache/'. $hashPath . $filePath, - $imageModel->getPath() - ); - } - - /** - * @param string $filePath - * @param array $miscParams - * @param string $readableParams - * @dataProvider getPathDataProvider - */ - public function testGetUrl($filePath, $miscParams, $readableParams) - { - $imageModel = $this->objectManager->getObject( - Image::class, - [ - 'mediaConfig' => $this->mediaConfig, - 'context' => $this->context, - 'encryptor' => $this->encryptor, - 'filePath' => $filePath, - 'assetRepo' => $this->assetRepo, - 'miscParams' => $miscParams - ] - ); - $absolutePath = 'http://localhost/pub/media/catalog/product'; - $hashPath = 'somehash'; - $this->context->expects(static::once())->method('getBaseUrl')->willReturn($absolutePath); - $this->encryptor->expects(static::once()) - ->method('hash') - ->with($readableParams, $this->anything()) - ->willReturn($hashPath); - static::assertEquals( - $absolutePath . '/cache/' . $hashPath . $filePath, - $imageModel->getUrl() - ); - } - - /** - * @return array - */ - public function getPathDataProvider() - { - return [ - [ - '/some_file.png', - [], //default value for miscParams, - 'h:empty_w:empty_q:empty_r:empty_nonproportional_noframe_notransparency_notconstrainonly_nobackground', - ], - [ - '/some_file_2.png', - [ - 'image_type' => 'thumbnail', - 'image_height' => 75, - 'image_width' => 75, - 'keep_aspect_ratio' => true, - 'keep_frame' => true, - 'keep_transparency' => true, - 'constrain_only' => true, - 'background' => [233,1,0], - 'angle' => null, - 'quality' => 80, - ], - 'h:75_w:75_proportional_frame_transparency_doconstrainonly_rgb233,1,0_r:empty_q:80', - ], - [ - '/some_file_3.png', - [ - 'image_type' => 'thumbnail', - 'image_height' => 75, - 'image_width' => 75, - 'keep_aspect_ratio' => false, - 'keep_frame' => false, - 'keep_transparency' => false, - 'constrain_only' => false, - 'background' => [233,1,0], - 'angle' => 90, - 'quality' => 80, - ], - 'h:75_w:75_nonproportional_noframe_notransparency_notconstrainonly_rgb233,1,0_r:90_q:80', - ], - ]; - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Listing/Collector/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Listing/Collector/ImageTest.php index 009cd690d4cd4..bd08a39fb2bed 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Listing/Collector/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Listing/Collector/ImageTest.php @@ -99,9 +99,6 @@ public function testGet() ->method('create') ->willReturn($image); - $imageHelper->expects($this->once()) - ->method('getResizedImageInfo') - ->willReturn([11, 11]); $this->state->expects($this->once()) ->method('emulateAreaCode') ->with( @@ -111,12 +108,14 @@ public function testGet() ) ->willReturn($imageHelper); + $width = 5; + $height = 10; $imageHelper->expects($this->once()) ->method('getHeight') - ->willReturn(10); + ->willReturn($height); $imageHelper->expects($this->once()) ->method('getWidth') - ->willReturn(10); + ->willReturn($width); $imageHelper->expects($this->once()) ->method('getLabel') ->willReturn('Label'); @@ -132,10 +131,10 @@ public function testGet() ->with(); $image->expects($this->once()) ->method('setResizedHeight') - ->with(11); + ->with($height); $image->expects($this->once()) ->method('setResizedWidth') - ->with(11); + ->with($width); $productRenderInfoDto->expects($this->once()) ->method('setImages') diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php index 09c9782fc0e32..52773b4580256 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php @@ -9,7 +9,7 @@ use Magento\Framework\View\Element\UiComponent\ContextInterface; /** - * Class Thumbnail + * Column with thumbnail images * * @api * @since 100.0.2 @@ -20,6 +20,16 @@ class Thumbnail extends \Magento\Ui\Component\Listing\Columns\Column const ALT_FIELD = 'name'; + /** + * @var \Magento\Catalog\Helper\Image + */ + private $imageHelper; + + /** + * @var \Magento\Framework\UrlInterface + */ + private $urlBuilder; + /** * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php index b4acb93dcd14f..b822a5e3ef88a 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Related.php @@ -25,7 +25,7 @@ use Magento\Catalog\Model\Product\Attribute\Source\Status; /** - * Class Related + * Related products modifier * * @api * @@ -143,7 +143,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc * @since 101.0.0 */ public function modifyMeta(array $meta) @@ -182,7 +182,7 @@ public function modifyMeta(array $meta) } /** - * {@inheritdoc} + * @inheritdoc * @since 101.0.0 */ public function modifyData(array $data) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/Collector/Image.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/Collector/Image.php index d8f76c40e8fad..45383ed51f6fc 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/Collector/Image.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Listing/Collector/Image.php @@ -118,18 +118,14 @@ public function collect(ProductInterface $product, ProductRenderInterface $produ [$product, $imageCode, (int) $productRender->getStoreId(), $image] ); - try { - $resizedInfo = $helper->getResizedImageInfo(); - } catch (NotLoadInfoImageException $exception) { - $resizedInfo = [$helper->getWidth(), $helper->getHeight()]; - } - $image->setCode($imageCode); - $image->setHeight($helper->getHeight()); - $image->setWidth($helper->getWidth()); + $height = $helper->getHeight(); + $image->setHeight($height); + $width = $helper->getWidth(); + $image->setWidth($width); $image->setLabel($helper->getLabel()); - $image->setResizedHeight($resizedInfo[1]); - $image->setResizedWidth($resizedInfo[0]); + $image->setResizedHeight($height); + $image->setResizedWidth($width); $images[] = $image; } diff --git a/app/code/Magento/Catalog/etc/adminhtml/system.xml b/app/code/Magento/Catalog/etc/adminhtml/system.xml index 80b323cfdb250..f59990cdcea96 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/system.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/system.xml @@ -208,6 +208,13 @@ <source_model>Magento\Catalog\Model\Config\Source\LayoutList</source_model> </field> </group> + <group id="url"> + <field id="catalog_media_url_format" translate="label comment" type="select" sortOrder="30" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> + <label>Catalog media URL format</label> + <source_model>Magento\Catalog\Model\Config\Source\Web\CatalogMediaUrlFormat</source_model> + <comment><![CDATA[Images should be optimized based on query parameters by your CDN or web server. Use the legacy mode for backward compatibility. <a href="https://docs.magento.com/m2/ee/user_guide/configuration/general/web.html#url-options">Learn more</a> about catalog URL formats.<br/><br/><strong style="color:red">Warning!</strong> If you switch back to legacy mode, you must <a href="https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/theme-images.html#resize-catalog-images">use the CLI to regenerate images</a>.]]></comment> + </field> + </group> </section> <section id="system" translate="label" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> diff --git a/app/code/Magento/Catalog/etc/config.xml b/app/code/Magento/Catalog/etc/config.xml index 59fc4b6d947d9..68289904db0cf 100644 --- a/app/code/Magento/Catalog/etc/config.xml +++ b/app/code/Magento/Catalog/etc/config.xml @@ -80,6 +80,11 @@ <thumbnail_position>stretch</thumbnail_position> </watermark> </design> + <web> + <url> + <catalog_media_url_format>hash</catalog_media_url_format> + </url> + </web> <general> <validator_data> <input_types> diff --git a/app/code/Magento/Checkout/CustomerData/DefaultItem.php b/app/code/Magento/Checkout/CustomerData/DefaultItem.php index 21580d1275d0c..23d5827dc1916 100644 --- a/app/code/Magento/Checkout/CustomerData/DefaultItem.php +++ b/app/code/Magento/Checkout/CustomerData/DefaultItem.php @@ -10,7 +10,7 @@ use Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface; /** - * Default item + * Default item in checkout customer data */ class DefaultItem extends AbstractItem { @@ -78,7 +78,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function doGetItemData() { @@ -121,6 +121,8 @@ protected function getOptionList() } /** + * Get product for thumbnail + * * @return \Magento\Catalog\Model\Product * @codeCoverageIgnore */ @@ -130,6 +132,8 @@ protected function getProductForThumbnail() } /** + * Get product + * * @return \Magento\Catalog\Model\Product * @codeCoverageIgnore */ diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index fdf49d6765a29..87585e4bf327f 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -31,7 +31,7 @@ use Magento\Ui\Component\Form\Element\Multiline; /** - * Default Config Provider + * Default Config Provider for checkout * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) diff --git a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php index 4ed84829c2ad0..7f19ba6c24cfa 100644 --- a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php +++ b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php @@ -84,7 +84,10 @@ public function __construct( protected function configure() { $this->setName('catalog:images:resize') - ->setDescription('Creates resized product images') + ->setDescription( + 'Creates resized product images ' . + '(Not relevant when image resizing is offloaded from Magento. See https://docs.magento.com/m2/ee/user_guide/configuration/general/web.html#url-options )' + ) ->setDefinition($this->getOptionsList()); } diff --git a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php index cf85fb633bbca..29b60ed44d5b1 100644 --- a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php @@ -19,7 +19,7 @@ class UpgradeInsecureTest extends \PHPUnit\Framework\TestCase /** * Content-Security-Policy header value */ - const HEADER_VALUE = 'upgrade-insecure-requests'; + const HEADER_VALUE = 'upgrade-insecure-requests;'; /** * @var UpgradeInsecure diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index ae54289d4b1c9..2f6b57a8650c4 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -68,7 +68,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getSectionData() { @@ -80,6 +80,8 @@ public function getSectionData() } /** + * Get counter + * * @return string */ protected function getCounter() @@ -156,7 +158,6 @@ protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) * * @param \Magento\Catalog\Model\Product $product * @return array - * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function getImageData($product) { @@ -164,27 +165,11 @@ protected function getImageData($product) $helper = $this->imageHelperFactory->create() ->init($product, 'wishlist_sidebar_block'); - $template = 'Magento_Catalog/product/image_with_borders'; - - try { - $imagesize = $helper->getResizedImageInfo(); - } catch (NotLoadInfoImageException $exception) { - $imagesize = [$helper->getWidth(), $helper->getHeight()]; - } - - $width = $helper->getFrame() - ? $helper->getWidth() - : $imagesize[0]; - - $height = $helper->getFrame() - ? $helper->getHeight() - : $imagesize[1]; - return [ - 'template' => $template, + 'template' => 'Magento_Catalog/product/image_with_borders', 'src' => $helper->getUrl(), - 'width' => $width, - 'height' => $height, + 'width' => $helper->getWidth(), + 'height' => $helper->getHeight(), 'alt' => $helper->getLabel(), ]; } diff --git a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php index 4954712e5ff3b..6d90d8b1a5fed 100644 --- a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php @@ -193,9 +193,6 @@ public function testGetSectionData() $this->catalogImageHelperMock->expects($this->any()) ->method('getFrame') ->willReturn(true); - $this->catalogImageHelperMock->expects($this->once()) - ->method('getResizedImageInfo') - ->willReturn([]); $this->wishlistHelperMock->expects($this->once()) ->method('getProductUrl') @@ -394,9 +391,6 @@ public function testGetSectionDataWithTwoItems() $this->catalogImageHelperMock->expects($this->any()) ->method('getFrame') ->willReturn(true); - $this->catalogImageHelperMock->expects($this->exactly(2)) - ->method('getResizedImageInfo') - ->willReturn([]); $this->wishlistHelperMock->expects($this->exactly(2)) ->method('getProductUrl') diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/GalleryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/GalleryTest.php index 9bcdb00eebe7c..a3545e4a39e80 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/GalleryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/GalleryTest.php @@ -120,9 +120,23 @@ public function testGetGalleryImagesJsonWithoutImages(): void $this->assertImages(reset($result), $this->placeholderExpectation); } + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoConfigFixture default/web/url/catalog_media_url_format image_optimization_parameters + * @magentoDbIsolation enabled + * @return void + */ + public function testGetGalleryImagesJsonWithoutImagesWithImageOptimizationParametersInUrl(): void + { + $this->block->setData('product', $this->getProduct()); + $result = $this->serializer->unserialize($this->block->getGalleryImagesJson()); + $this->assertImages(reset($result), $this->placeholderExpectation); + } + /** * @dataProvider galleryDisabledImagesDataProvider * @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php + * @magentoConfigFixture default/web/url/catalog_media_url_format hash * @magentoDbIsolation enabled * @param array $images * @param array $expectation @@ -141,6 +155,7 @@ public function testGetGalleryImagesJsonWithDisabledImage(array $images, array $ * @dataProvider galleryDisabledImagesDataProvider * @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoConfigFixture default/web/url/catalog_media_url_format hash * @magentoDbIsolation disabled * @param array $images * @param array $expectation @@ -173,6 +188,8 @@ public function galleryDisabledImagesDataProvider(): array } /** + * Test default image generation format. + * * @dataProvider galleryImagesDataProvider * @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php * @magentoDbIsolation enabled @@ -230,10 +247,95 @@ public function galleryImagesDataProvider(): array ]; } + /** + * @dataProvider galleryImagesWithImageOptimizationParametersInUrlDataProvider + * @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php + * @magentoConfigFixture default/web/url/catalog_media_url_format image_optimization_parameters + * @magentoDbIsolation enabled + * @param array $images + * @param array $expectation + * @return void + */ + public function testGetGalleryImagesJsonWithImageOptimizationParametersInUrl( + array $images, + array $expectation + ): void { + $product = $this->getProduct(); + $this->setGalleryImages($product, $images); + $this->block->setData('product', $this->getProduct()); + [$firstImage, $secondImage] = $this->serializer->unserialize($this->block->getGalleryImagesJson()); + [$firstExpectedImage, $secondExpectedImage] = $expectation; + $this->assertImages($firstImage, $firstExpectedImage); + $this->assertImages($secondImage, $secondExpectedImage); + } + + /** + * @return array + */ + public function galleryImagesWithImageOptimizationParametersInUrlDataProvider(): array + { + + $imageExpectation = [ + 'thumb' => '/m/a/magento_image.jpg?width=88&height=110&store=default&image-type=thumbnail', + 'img' => '/m/a/magento_image.jpg?width=700&height=700&store=default&image-type=image', + 'full' => '/m/a/magento_image.jpg?store=default&image-type=image', + 'caption' => 'Image Alt Text', + 'position' => '1', + 'isMain' => false, + 'type' => 'image', + 'videoUrl' => null, + ]; + + $thumbnailExpectation = [ + 'thumb' => '/m/a/magento_thumbnail.jpg?width=88&height=110&store=default&image-type=thumbnail', + 'img' => '/m/a/magento_thumbnail.jpg?width=700&height=700&store=default&image-type=image', + 'full' => '/m/a/magento_thumbnail.jpg?store=default&image-type=image', + 'caption' => 'Thumbnail Image', + 'position' => '2', + 'isMain' => false, + 'type' => 'image', + 'videoUrl' => null, + ]; + + return [ + 'with_main_image' => [ + 'images' => [ + '/m/a/magento_image.jpg' => [], + '/m/a/magento_thumbnail.jpg' => ['main' => true], + ], + 'expectation' => [ + $imageExpectation, + array_merge($thumbnailExpectation, ['isMain' => true]), + ], + ], + 'without_main_image' => [ + 'images' => [ + '/m/a/magento_image.jpg' => [], + '/m/a/magento_thumbnail.jpg' => [], + ], + 'expectation' => [ + array_merge($imageExpectation, ['isMain' => true]), + $thumbnailExpectation, + ], + ], + 'with_changed_position' => [ + 'images' => [ + '/m/a/magento_image.jpg' => ['position' => '2'], + '/m/a/magento_thumbnail.jpg' => ['position' => '1'], + ], + 'expectation' => [ + array_merge($thumbnailExpectation, ['position' => '1']), + array_merge($imageExpectation, ['position' => '2', 'isMain' => true]), + ], + ], + ]; + } + /** * @dataProvider galleryImagesOnStoreViewDataProvider * @magentoDataFixture Magento/Catalog/_files/product_with_multiple_images.php * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoConfigFixture default/web/url/catalog_media_url_format hash * @magentoDbIsolation disabled * @param array $images * @param array $expectation diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php index 383af7968e047..46e9ba667f390 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Service/PaymentFailuresServiceTest.php @@ -82,7 +82,6 @@ public function testHandlerWithCustomer(): void $expectedVars = [ 'reason' => $errorMessage, 'checkoutType' => $checkoutType, - 'dateAndTime' => $templateTimeMethod->invoke($this->paymentFailures), 'customer' => 'John Smith', 'customerEmail' => 'aaa@aaa.com', 'paymentMethod' => 'Some Title Of The Method', @@ -94,6 +93,7 @@ public function testHandlerWithCustomer(): void 'billingAddressHtml' => $this->quote->getBillingAddress()->format('html'), 'shippingAddressHtml' => $this->quote->getShippingAddress()->format('html'), ]; + unset($templateVars['dateAndTime']); $this->assertEquals($expectedVars, $templateVars); } diff --git a/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php b/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php index d6388b188a5fd..7d5e919880d3b 100644 --- a/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Sitemap/Model/ResourceModel/Catalog/ProductTest.php @@ -52,6 +52,7 @@ public function testGetCollectionNone() * 3) Check thumbnails when no thumbnail selected * * @magentoConfigFixture default_store sitemap/product/image_include all + * @magentoConfigFixture default/web/url/catalog_media_url_format hash */ public function testGetCollectionAll() { @@ -120,6 +121,7 @@ public function testGetCollectionAll() * 3) Check thumbnails when no thumbnail selected * * @magentoConfigFixture default_store sitemap/product/image_include base + * @magentoConfigFixture default/web/url/catalog_media_url_format hash */ public function testGetCollectionBase() { diff --git a/nginx.conf.sample b/nginx.conf.sample index 9219400f6aacd..f045edb46a1c2 100644 --- a/nginx.conf.sample +++ b/nginx.conf.sample @@ -26,6 +26,9 @@ ## ## In production mode, you should uncomment the 'expires' directive in the /static/ location block +# Modules can be loaded only at the very beginning of the Nginx config file, please move the line below to the main config file +# load_module /etc/nginx/modules/ngx_http_image_filter_module.so; + root $MAGE_ROOT/pub; index index.php; @@ -134,6 +137,28 @@ location /static/ { } location /media/ { + +## The following section allows to offload image resizing from Magento instance to the Nginx. +## Catalog image URL format should be set accordingly. +## See https://docs.magento.com/m2/ee/user_guide/configuration/general/web.html#url-options +# location ~* ^/media/catalog/.* { +# +# # Replace placeholders and uncomment the line below to serve product images from public S3 +# # See examples of S3 authentication at https://github.com/anomalizer/ngx_aws_auth +# # proxy_pass https://<bucket-name>.<region-name>.amazonaws.com; +# +# set $width "-"; +# set $height "-"; +# if ($arg_width != '') { +# set $width $arg_width; +# } +# if ($arg_height != '') { +# set $height $arg_height; +# } +# image_filter resize $width $height; +# image_filter_jpeg_quality 90; +# } + try_files $uri $uri/ /get.php$is_args$args; location ~ ^/media/theme_customization/.*\.xml { From a7504d71fa23881def23c99b380712e810600365 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Wed, 29 Jan 2020 17:32:00 +0100 Subject: [PATCH 359/666] Add frontend template hints status command unit tests after suggestions --- .../Developer/Console/Command/TemplateHintsStatusCommand.php | 2 +- .../Unit/Console/Command/TemplateHintsStatusCommandTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index 42e2d214a330c..d6569622d17ce 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -70,7 +70,7 @@ public function execute(InputInterface $input, OutputInterface $output) ? 'enabled' : 'disabled'; $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); - $output->writeln("<info>" . $templateHintsMessage . "</info>"); + $output->writeln("<info>$templateHintsMessage</info>"); return Cli::RETURN_SUCCESS; } diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php index f3acb5d2e1f5e..1c7ecaf161003 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -25,7 +25,6 @@ class TemplateHintsStatusCommandTest extends TestCase * @var TemplateHintsStatusCommand */ private $command; - /** * @var ScopeConfigInterface */ From bb8ba6e33b1600800044f2d3d4b014a010028fe0 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 29 Jan 2020 18:40:52 +0200 Subject: [PATCH 360/666] MC-25260: A wrong behaviour of a chart order --- .../Backend/Block/Dashboard/Tab/OrdersTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 index f5b730173e596..1ac68b8d7ff57 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Dashboard/Tab/OrdersTest.php @@ -46,7 +46,6 @@ protected function setUp() } /** - * @magentoDbIsolation disabled * @magentoDataFixture Magento/Sales/_files/order_list_with_invoice.php * @dataProvider chartUrlDataProvider * @param string $period @@ -58,8 +57,7 @@ public function testGetChartUrl(string $period, string $expectedAxisRange): void $this->graphBlock->getRequest()->setParams(['period' => $period]); $ordersBlock = $this->layout->createBlock(Orders::class); $decodedChartUrl = urldecode($ordersBlock->getChartUrl()); - $chartUrlSegments = explode('&', $decodedChartUrl); - $this->assertEquals($expectedAxisRange, $this->getUrlParamData($chartUrlSegments, 'chxr')); + $this->assertEquals($expectedAxisRange, $this->getUrlParamData($decodedChartUrl, 'chxr')); } /** @@ -77,18 +75,20 @@ public function chartUrlDataProvider(): array } /** - * @param array $chartUrlSegments + * @param string $chartUrl * @param string $paramName * @return string */ - private function getUrlParamData(array $chartUrlSegments, string $paramName): string + private function getUrlParamData(string $chartUrl, string $paramName): string { - $urlParams = []; + $chartUrlSegments = explode('&', $chartUrl); foreach ($chartUrlSegments as $chartUrlSegment) { - list($paramKey, $paramValue) = explode('=', $chartUrlSegment); - $urlParams[$paramKey] = $paramValue; + [$paramKey, $paramValue] = explode('=', $chartUrlSegment); + if ($paramKey === $paramName) { + return $paramValue; + } } - return $urlParams[$paramName] ?? ''; + return ''; } } From e165d99f5994af39d49ed70155c003745158e5db Mon Sep 17 00:00:00 2001 From: Yevhen Sentiabov <sentiabo@adobe.com> Date: Wed, 29 Jan 2020 10:53:49 -0600 Subject: [PATCH 361/666] Github #26532: di:setup:compile fails with anonymous classes - Small refactoring for code simplification --- .../Module/Di/Code/Scanner/PhpScanner.php | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php index be25cf605ef80..c7aa6fc6eb0c3 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Scanner/PhpScanner.php @@ -10,8 +10,8 @@ use Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator; use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator; use Magento\Framework\ObjectManager\Code\Generator\Factory as FactoryGenerator; +use Magento\Framework\Reflection\TypeProcessor; use Magento\Setup\Module\Di\Compiler\Log\Log; -use \Magento\Framework\Reflection\TypeProcessor; /** * Finds factory and extension attributes classes which require auto-generation. @@ -50,7 +50,7 @@ public function __construct(Log $log, TypeProcessor $typeProcessor = null) * @param string $entityType * @return string[] */ - protected function _findMissingClasses($file, $classReflection, $methodName, $entityType) + private function findMissingFactories($file, $classReflection, $methodName, $entityType) { $missingClasses = []; if (!$classReflection->hasMethod($methodName)) { @@ -123,7 +123,7 @@ protected function getSourceClassName($missingClassName, $entityType) */ protected function _fetchFactories($reflectionClass, $file) { - $absentFactories = $this->_findMissingClasses( + $absentFactories = $this->findMissingFactories( $file, $reflectionClass, '__construct', @@ -177,11 +177,11 @@ public function collectEntities(array $files) { $output = [[]]; foreach ($files as $file) { - $classes = $this->_getDeclaredClasses($file); + $classes = $this->getDeclaredClasses($file); foreach ($classes as $className) { $reflectionClass = new \ReflectionClass($className); - $output [] = $this->_fetchFactories($reflectionClass, $file); - $output [] = $this->_fetchMissingExtensionAttributesClasses($reflectionClass, $file); + $output[] = $this->_fetchFactories($reflectionClass, $file); + $output[] = $this->_fetchMissingExtensionAttributesClasses($reflectionClass, $file); } } return array_unique(array_merge(...$output)); @@ -210,32 +210,30 @@ protected function _fetchNamespace($tokenIterator, $count, $tokens) } /** - * Fetch class names from tokenized PHP file + * Fetches class name from tokenized PHP file. * * @param string $namespace * @param int $tokenIterator * @param int $count * @param array $tokens - * @return array + * @return string|null */ - protected function _fetchClasses($namespace, $tokenIterator, $count, $tokens) + private function fetchClass($namespace, $tokenIterator, $count, $tokens):? string { - $classes = []; + // anonymous classes should be omitted + if (is_array($tokens[$tokenIterator - 2]) && $tokens[$tokenIterator - 2][0] === T_NEW) { + return null; + } + for ($tokenOffset = $tokenIterator + 1; $tokenOffset < $count; ++$tokenOffset) { if ($tokens[$tokenOffset] !== '{') { continue; } - // anonymous classes should be omitted - if (is_array($tokens[$tokenIterator - 2]) && $tokens[$tokenIterator - 2][0] === T_NEW) { - continue; - } - $class = $namespace . "\\" . $tokens[$tokenIterator + 2][1]; - if (!in_array($class, $classes)) { - $classes[] = $class; - } + return $namespace . "\\" . $tokens[$tokenIterator + 2][1]; } - return $classes; + + return null; } /** @@ -244,9 +242,9 @@ protected function _fetchClasses($namespace, $tokenIterator, $count, $tokens) * @param string $file * @return array */ - protected function _getDeclaredClasses($file) + private function getDeclaredClasses($file): array { - $classes = [[]]; + $classes = []; $namespaceParts = []; // phpcs:ignore $tokens = token_get_all(file_get_contents($file)); @@ -260,10 +258,13 @@ protected function _getDeclaredClasses($file) if (($tokens[$tokenIterator][0] == T_CLASS || $tokens[$tokenIterator][0] == T_INTERFACE) && $tokens[$tokenIterator - 1][0] != T_DOUBLE_COLON ) { - $classes[] = $this->_fetchClasses(join('', $namespaceParts), $tokenIterator, $count, $tokens); + $class = $this->fetchClass(join('', $namespaceParts), $tokenIterator, $count, $tokens); + if ($class !== null && !in_array($class, $classes)) { + $classes[] = $class; + } } } - return array_unique(array_merge(...$classes)); + return $classes; } /** From 1000bcd1bfe1380c613b0486e1557e1acec18958 Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Wed, 29 Jan 2020 19:48:33 +0200 Subject: [PATCH 362/666] Fix issue related with UnitTest --- .../Magento/Sales/Block/Status/Grid/Column/State.php | 10 ++++++---- .../Test/Unit/Block/Status/Grid/Column/StateTest.php | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index 51d9886c79b67..7639bde75898c 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -57,10 +57,12 @@ public function decorateState($value, $row, $column, $isExport) { $states = $this->_config->getStates(); if (isset($states[$value])) { - $cell = $value . '[' . $states[$value] . ']'; - } else { - $cell = $value; + return sprintf("%s[%s]", + $value, + $states[$value] + ); } - return $cell; + + return $value; } } diff --git a/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php b/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php index 86e0c561ca5ee..76ebeb2487ef3 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php @@ -55,6 +55,7 @@ public function testDecorateState() [ 'status' => 'fraud', 'state' => 'processing', + 'is_default' => '0', 'label' => 'Suspected Fraud', ] ), @@ -62,6 +63,7 @@ public function testDecorateState() [ 'status' => 'processing', 'state' => 'processing', + 'is_default' => '1', 'label' => 'Processing', ] ) @@ -78,6 +80,6 @@ public function testDecorateState() ->will($this->returnValue($statuses)); $result = $this->stateColumn->decorateState('processing', $rowMock, $columnMock, false); - $this->assertSame('processing[Suspected Fraud]', $result); + $this->assertSame('processing[Processing]', $result); } } From ae47540b5a1934bf8b47dc56fe65e4bed40191c0 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Wed, 29 Jan 2020 13:32:55 -0600 Subject: [PATCH 363/666] ECP-261: Offload Catalog Image Resizing from Magento - Fixed tests - Suppressed excessive coupling warning in Helper/Image because it is an @api class with dependencies in protected properties (cannot be refactored in backward compatible manner) --- app/code/Magento/Catalog/Helper/Image.php | 9 +++++---- .../MediaStorage/Console/Command/ImagesResizeCommand.php | 3 ++- .../Unit/Model/HeaderProvider/UpgradeInsecureTest.php | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index 191f5eee1b5e1..3e0976936329c 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -13,10 +13,11 @@ use Magento\Framework\View\Element\Block\ArgumentInterface; /** - * Catalog image helper + * Catalog image helper. * * @api * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ class Image extends AbstractHelper implements ArgumentInterface @@ -163,8 +164,7 @@ public function __construct( $this->_assetRepo = $assetRepo; $this->viewConfig = $viewConfig; $this->viewAssetPlaceholderFactory = $placeholderFactory - ?: ObjectManager::getInstance() - ->get(PlaceholderFactory::class); + ?: ObjectManager::getInstance()->get(PlaceholderFactory::class); $this->mediaConfig = $mediaConfig ?: ObjectManager::getInstance()->get(CatalogMediaConfig::class); } @@ -394,9 +394,10 @@ public function constrainOnly($flag) */ public function backgroundColor($colorRGB) { + $args = func_get_args(); // assume that 3 params were given instead of array if (!is_array($colorRGB)) { - $colorRGB = func_get_args(); + $colorRGB = $args; } $this->_getModel()->setBackgroundColor($colorRGB); return $this; diff --git a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php index 7f19ba6c24cfa..d592a004e111a 100644 --- a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php +++ b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php @@ -86,7 +86,8 @@ protected function configure() $this->setName('catalog:images:resize') ->setDescription( 'Creates resized product images ' . - '(Not relevant when image resizing is offloaded from Magento. See https://docs.magento.com/m2/ee/user_guide/configuration/general/web.html#url-options )' + '(Not relevant when image resizing is offloaded from Magento. ' . + 'See https://docs.magento.com/m2/ee/user_guide/configuration/general/web.html#url-options )' ) ->setDefinition($this->getOptionsList()); } diff --git a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php index 29b60ed44d5b1..cf85fb633bbca 100644 --- a/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/HeaderProvider/UpgradeInsecureTest.php @@ -19,7 +19,7 @@ class UpgradeInsecureTest extends \PHPUnit\Framework\TestCase /** * Content-Security-Policy header value */ - const HEADER_VALUE = 'upgrade-insecure-requests;'; + const HEADER_VALUE = 'upgrade-insecure-requests'; /** * @var UpgradeInsecure From 9c11369cea37527da27c63108b8e18fa3b56ee9d Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Thu, 30 Jan 2020 01:13:32 +0530 Subject: [PATCH 364/666] #26583 tier pricing save percent showing logic updated --- .../Catalog/view/base/templates/product/price/tier_prices.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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..403e342c215ea 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 @@ -77,7 +77,7 @@ $product = $block->getSaleableItem(); $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); ?> From ad184d23efcea17cd1d5fe84849b38ed9f1b6636 Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Wed, 29 Jan 2020 21:49:08 +0200 Subject: [PATCH 365/666] fix code style issue --- app/code/Magento/Sales/Block/Status/Grid/Column/State.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index 7639bde75898c..b66587eef5831 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -59,8 +59,7 @@ public function decorateState($value, $row, $column, $isExport) if (isset($states[$value])) { return sprintf("%s[%s]", $value, - $states[$value] - ); + $states[$value]); } return $value; From 6e2d0c841cb716fefd831fe1667acd2013e00c28 Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Wed, 29 Jan 2020 22:43:58 +0200 Subject: [PATCH 366/666] fixed codeStyle issues --- app/code/Magento/Sales/Block/Status/Grid/Column/State.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index b66587eef5831..10f8edb524c34 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -57,9 +57,11 @@ public function decorateState($value, $row, $column, $isExport) { $states = $this->_config->getStates(); if (isset($states[$value])) { - return sprintf("%s[%s]", + return sprintf( + "%s[%s]", $value, - $states[$value]); + $states[$value] + ); } return $value; From 8e2959de1740f78ba9a57aa0e21e23ecca79dcc6 Mon Sep 17 00:00:00 2001 From: Jeroen <jeroen@reachdigital.nl> Date: Mon, 2 Dec 2019 12:25:28 +0100 Subject: [PATCH 367/666] Prevent endless loop when duplicating product --- .../Magento/Catalog/Model/Product/Copier.php | 81 ++++---- .../Test/Unit/Model/Product/CopierTest.php | 177 +++++++++++++++--- 2 files changed, 185 insertions(+), 73 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index a7f7bad1a5167..d10bf085a4a25 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -8,7 +8,11 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Attribute\ScopeOverriddenValue; use Magento\Catalog\Model\Product; +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\UrlRewrite\Model\Exception\UrlAlreadyExistsException; /** * Catalog product copier. @@ -35,9 +39,10 @@ class Copier protected $productFactory; /** - * @var \Magento\Framework\EntityManager\MetadataPool + * @var MetadataPool */ protected $metadataPool; + /** * @var ScopeOverriddenValue */ @@ -47,30 +52,38 @@ class Copier * @param CopyConstructorInterface $copyConstructor * @param ProductFactory $productFactory * @param ScopeOverriddenValue $scopeOverriddenValue + * @param OptionRepository|null $optionRepository + * @param MetadataPool|null $metadataPool */ public function __construct( CopyConstructorInterface $copyConstructor, ProductFactory $productFactory, - ScopeOverriddenValue $scopeOverriddenValue + ScopeOverriddenValue $scopeOverriddenValue, + OptionRepository $optionRepository = null, + MetadataPool $metadataPool = null ) { $this->productFactory = $productFactory; $this->copyConstructor = $copyConstructor; $this->scopeOverriddenValue = $scopeOverriddenValue; + $this->optionRepository = $optionRepository ?: ObjectManager::getInstance()->get(OptionRepository::class); + $this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class); } /** * Create product duplicate * * @param \Magento\Catalog\Model\Product $product + * * @return \Magento\Catalog\Model\Product + * + * @throws \Exception */ public function copy(Product $product) { $product->getWebsiteIds(); $product->getCategoryIds(); - /** @var \Magento\Framework\EntityManager\EntityMetadataInterface $metadata */ - $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class); + $metadata = $this->metadataPool->getMetadata(ProductInterface::class); /** @var \Magento\Catalog\Model\Product $duplicate */ $duplicate = $this->productFactory->create(); @@ -88,7 +101,7 @@ public function copy(Product $product) $this->copyConstructor->build($product, $duplicate); $this->setDefaultUrl($product, $duplicate); $this->setStoresUrl($product, $duplicate); - $this->getOptionRepository()->duplicate($product, $duplicate); + $this->optionRepository->duplicate($product, $duplicate); $product->getResource()->duplicate( $product->getData($metadata->getLinkField()), $duplicate->getData($metadata->getLinkField()) @@ -123,13 +136,16 @@ private function setDefaultUrl(Product $product, Product $duplicate) : void * * @param Product $product * @param Product $duplicate + * * @return void + * @throws UrlAlreadyExistsException */ private function setStoresUrl(Product $product, Product $duplicate) : void { $storeIds = $duplicate->getStoreIds(); $productId = $product->getId(); $productResource = $product->getResource(); + $attribute = $productResource->getAttribute('url_key'); $duplicate->setData('save_rewrites_history', false); foreach ($storeIds as $storeId) { $useDefault = !$this->scopeOverriddenValue->containsValue( @@ -141,20 +157,23 @@ private function setStoresUrl(Product $product, Product $duplicate) : void if ($useDefault) { continue; } - $isDuplicateSaved = false; + $duplicate->setStoreId($storeId); $urlKey = $productResource->getAttributeRawValue($productId, 'url_key', $storeId); + $iteration = 0; + do { + if ($iteration === 10) { + throw new UrlAlreadyExistsException(); + } + $urlKey = $this->modifyUrl($urlKey); $duplicate->setUrlKey($urlKey); - $duplicate->setData('url_path', null); - try { - $duplicate->save(); - $isDuplicateSaved = true; - // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock - } catch (\Magento\Framework\Exception\AlreadyExistsException $e) { - } - } while (!$isDuplicateSaved); + $iteration++; + } while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate)); + $duplicate->setData('url_path', null); + $productResource->saveAttribute($duplicate, 'url_path'); + $productResource->saveAttribute($duplicate, 'url_key'); } $duplicate->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID); } @@ -168,38 +187,8 @@ private function setStoresUrl(Product $product, Product $duplicate) : void private function modifyUrl(string $urlKey) : string { return preg_match('/(.*)-(\d+)$/', $urlKey, $matches) - ? $matches[1] . '-' . ($matches[2] + 1) - : $urlKey . '-1'; - } - - /** - * Returns product option repository. - * - * @return Option\Repository - * @deprecated 101.0.0 - */ - private function getOptionRepository() - { - if (null === $this->optionRepository) { - $this->optionRepository = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Catalog\Model\Product\Option\Repository::class); - } - return $this->optionRepository; - } - - /** - * Returns metadata pool. - * - * @return \Magento\Framework\EntityManager\MetadataPool - * @deprecated 101.0.0 - */ - private function getMetadataPool() - { - if (null === $this->metadataPool) { - $this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\EntityManager\MetadataPool::class); - } - return $this->metadataPool; + ? $matches[1] . '-' . ($matches[2] + 1) + : $urlKey . '-1'; } /** 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 809fa0225278c..1d5abd817deb5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -6,7 +6,6 @@ namespace Magento\Catalog\Test\Unit\Model\Product; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Attribute\ScopeOverriddenValue; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Copier; @@ -40,17 +39,17 @@ class CopierTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $productMock; + private $scopeOverriddenValueMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $metadata; + protected $productMock; /** - * @var ScopeOverriddenValue|\PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit_Framework_MockObject_MockObject */ - private $scopeOverriddenValue; + protected $metadata; protected function setUp() { @@ -59,13 +58,14 @@ protected function setUp() \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->optionRepositoryMock; $this->productMock = $this->createMock(Product::class); $this->productMock->expects($this->any())->method('getEntityId')->willReturn(1); - $this->scopeOverriddenValue = $this->createMock(ScopeOverriddenValue::class); $this->metadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadata::class) ->disableOriginalConstructor() @@ -74,20 +74,16 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); $metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata); - $this->_model = new Copier( $this->copyConstructorMock, $this->productFactoryMock, - $this->scopeOverriddenValue + $this->scopeOverriddenValueMock ); - $this->setProperties( - $this->_model, - [ - 'optionRepository' => $this->optionRepositoryMock, - 'metadataPool' => $metadataPool, - ] - ); + $this->setProperties($this->_model, [ + 'optionRepository' => $this->optionRepositoryMock, + 'metadataPool' => $metadataPool + ]); } /** @@ -115,12 +111,10 @@ public function testCopy() ]; $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->any())->method('getData')->willReturnMap([ + ['', null, $productData], + ['linkField', null, '1'], + ]); $entityMock = $this->getMockForAbstractClass( \Magento\Eav\Model\Entity\AbstractEntity::class, @@ -205,11 +199,9 @@ public function testCopy() $this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField'); - $duplicateMock->expects($this->any())->method('getData')->willReturnMap( - [ - ['linkField', null, '2'], - ] - ); + $duplicateMock->expects($this->any())->method('getData')->willReturnMap([ + ['linkField', null, '2'], + ]); $this->optionRepositoryMock->expects($this->once()) ->method('duplicate') ->with($this->productMock, $duplicateMock); @@ -218,6 +210,137 @@ public function testCopy() $this->assertEquals($duplicateMock, $this->_model->copy($this->productMock)); } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl() + { + $stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class) + ->getMock(); + $extensionAttributes = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class) + ->setMethods(['getStockItem', 'setData']) + ->getMock(); + $extensionAttributes + ->expects($this->once()) + ->method('getStockItem') + ->willReturn($stockItem); + $extensionAttributes + ->expects($this->once()) + ->method('setData') + ->with('stock_item', null); + + $productData = [ + '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'], + ]); + + $entityMock = $this->getMockForAbstractClass( + \Magento\Eav\Model\Entity\AbstractEntity::class, + [], + '', + false, + true, + true, + ['checkAttributeUniqueValue'] + ); + $entityMock->expects($this->exactly(11)) + ->method('checkAttributeUniqueValue') + ->willReturn(true, false); + + $attributeMock = $this->getMockForAbstractClass( + \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class, + [], + '', + false, + true, + true, + ['getEntity'] + ); + $attributeMock->expects($this->any()) + ->method('getEntity') + ->willReturn($entityMock); + + $resourceMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getAttributeRawValue', 'duplicate', 'getAttribute']) + ->getMock(); + $resourceMock->expects($this->any()) + ->method('getAttributeRawValue') + ->willReturn('urk-key-1'); + $resourceMock->expects($this->any()) + ->method('getAttribute') + ->willReturn($attributeMock); + + $this->productMock->expects($this->any())->method('getResource')->will($this->returnValue($resourceMock)); + + $duplicateMock = $this->createPartialMock( + Product::class, + [ + '__wakeup', + 'setData', + 'setOptions', + 'getData', + 'setIsDuplicate', + 'setOriginalLinkId', + 'setStatus', + 'setCreatedAt', + 'setUpdatedAt', + 'setId', + 'getEntityId', + 'save', + 'setUrlKey', + 'setStoreId', + 'getStoreIds', + ] + ); + $this->productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($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->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([1]); + $duplicateMock->expects($this->atLeastOnce())->method('setData')->willReturn($duplicateMock); + $this->copyConstructorMock->expects($this->once())->method('build')->with($this->productMock, $duplicateMock); + $duplicateMock->expects( + $this->exactly(11) + )->method( + 'setUrlKey' + )->with( + $this->stringContains('urk-key-') + )->willReturn( + $duplicateMock + ); + $duplicateMock->expects($this->once())->method('save'); + + $this->scopeOverriddenValueMock->expects($this->once())->method('containsValue')->willReturn(true); + + $this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField'); + + $duplicateMock->expects($this->any())->method('getData')->willReturnMap([ + ['linkField', null, '2'], + ]); + + $this->expectException(\Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException::class); + $this->_model->copy($this->productMock); + } + /** * @param $object * @param array $properties From 5474b5f90a853378ac673f296047da09a0e510d5 Mon Sep 17 00:00:00 2001 From: Oleh Usik <o.usik@atwix.com> Date: Thu, 30 Jan 2020 11:33:52 +0200 Subject: [PATCH 368/666] Rewrite methods which was removed in first commit --- app/code/Magento/Sales/Model/Order/Config.php | 19 +++++++++++ .../Test/Unit/Model/Order/ConfigTest.php | 32 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/app/code/Magento/Sales/Model/Order/Config.php b/app/code/Magento/Sales/Model/Order/Config.php index 7dbddcd0a16c4..92681f3ecf181 100644 --- a/app/code/Magento/Sales/Model/Order/Config.php +++ b/app/code/Magento/Sales/Model/Order/Config.php @@ -300,4 +300,23 @@ protected function _getStatuses($visibility) } return $this->statuses[(bool) $visibility]; } + + /** + * Retrieve label by state and status + * + * @param string $state + * @param string $status + * @return \Magento\Framework\Phrase|string + * @since 100.2.0 + */ + public function getStateLabelByStateAndStatus($state, $status) + { + foreach ($this->_getCollection() as $item) { + if ($item->getData('state') == $state && $item->getData('status') == $status) { + $label = $item->getData('label'); + return __($label); + } + } + return $state; + } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php index 2dcc3c2a9fd24..0bd20150cd450 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php @@ -116,6 +116,38 @@ public function testGetInvisibleOnFrontStatuses() $this->assertSame($expectedResult, $result); } + /** + * @return void + */ + public function testGetStateLabelByStateAndStatus() + { + $statuses = [ + new DataObject( + [ + 'status' => 'fraud', + 'state' => 'processing', + 'label' => 'Suspected Fraud', + ] + ), + new DataObject( + [ + 'status' => 'processing', + 'state' => 'processing', + 'label' => 'Processing', + ] + ) + ]; + $collectionMock = $this->createPartialMock(Collection::class, ['create', 'joinStates']); + $this->orderStatusCollectionFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->once()) + ->method('joinStates') + ->will($this->returnValue($statuses)); + $result = $this->salesConfig->getStateLabelByStateAndStatus('processing', 'fraud'); + $this->assertSame('Suspected Fraud', $result->getText()); + } + /** * Test get statuses * From 56daae0ce5f2b0805683786b54c1a65c26fc2e28 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 12:01:59 +0200 Subject: [PATCH 369/666] Cover cjanges with jasmine test --- .../js/grid/columns/image-preview.test.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) 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..e40a64c9c9c17 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 @@ -46,5 +46,37 @@ define([ }); }); + + describe('handleKeyDown method', function () { + it('veify record changed on key down', function () { + var recordMock = { + _rowIndex: 2 + }, + secondRecordMock = { + _rowIndex: 1, + rowNumber: 1 + }, + elementMock = { + keyCode: 37 + }, + masonryMock = { + shows: jasmine.createSpy().and.returnValue([]), + rows: jasmine.createSpy().and.returnValue({ + 1: secondRecordMock + }) + + }, + imageMock = document.createElement('img'); + + 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); + }); + + }); }); }); From 581ac89489128c3a0bcc4f8558413fbe8a4a43f8 Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Thu, 30 Jan 2020 12:52:47 +0200 Subject: [PATCH 370/666] MC-23940: Removing websites or stores together with their configuration from config.php fails --- .../Model/Config/Importer/SaveProcessor.php | 11 ++++--- .../Config/Importer/SaveProcessorTest.php | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Config/Model/Config/Importer/SaveProcessor.php b/app/code/Magento/Config/Model/Config/Importer/SaveProcessor.php index 2ea9df52c0a03..225729f69a74e 100644 --- a/app/code/Magento/Config/Model/Config/Importer/SaveProcessor.php +++ b/app/code/Magento/Config/Model/Config/Importer/SaveProcessor.php @@ -91,6 +91,7 @@ public function process(array $data) * @param string $scope The configuration scope (default, website, or store) * @param string $scopeCode The scope code * @return void + * @throws \Magento\Framework\Exception\RuntimeException */ private function invokeSave(array $scopeData, $scope, $scopeCode = null) { @@ -98,11 +99,13 @@ private function invokeSave(array $scopeData, $scope, $scopeCode = null) foreach ($scopeData as $path) { $value = $this->scopeConfig->getValue($path, $scope, $scopeCode); - $backendModel = $this->valueFactory->create($path, $value, $scope, $scopeCode); + if ($value !== null) { + $backendModel = $this->valueFactory->create($path, $value, $scope, $scopeCode); - if ($backendModel instanceof Value) { - $backendModel->beforeSave(); - $backendModel->afterSave(); + if ($backendModel instanceof Value) { + $backendModel->beforeSave(); + $backendModel->afterSave(); + } } } } diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Importer/SaveProcessorTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Importer/SaveProcessorTest.php index aec3a6f64fec0..39a0e14f3e91c 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Importer/SaveProcessorTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Importer/SaveProcessorTest.php @@ -136,4 +136,37 @@ public function testProcess() $this->assertSame(null, $this->model->process($data)); } + + public function testProcessWithNullValues() + { + $data = [ + 'default' => [ + 'advanced' => ['modules_disable_output' => ['Test_Module' => '1']] + ], + 'websites' => ['test_website' => ['general' => ['locale' => ['timezone' => 'America/Rio_Branco']]]], + ]; + $this->arrayUtilsMock->expects($this->exactly(2)) + ->method('flatten') + ->willReturnMap([ + [ + [ + 'advanced' => ['modules_disable_output' => ['Test_Module' => '1']] + ], + '', + '/', + ['advanced/modules_disable_output/Test_Module' => '1'] + ], + [ + ['general' => ['locale' => ['timezone' => 'America/Rio_Branco']]], + '', + '/', + ['general/locale/timezone' => 'America/Rio_Branco'] + ] + ]); + $this->scopeConfigMock->expects($this->exactly(2)) + ->method('getValue') + ->willReturn(null); + + $this->assertSame(null, $this->model->process($data)); + } } From edc16d5f70dfd1ea3b0223834c657b7ab576826f Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 12:53:16 +0200 Subject: [PATCH 371/666] Destroy spy after test --- .../Magento/Ui/base/js/grid/columns/image-preview.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 e40a64c9c9c17..38c7003f08838 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 @@ -66,7 +66,8 @@ define([ }) }, - imageMock = document.createElement('img'); + imageMock = document.createElement('img'), + originMock = $.fn.get; spyOn($.fn, 'get').and.returnValue(imageMock); imagePreview.visibleRecord = jasmine.createSpy().and.returnValue(2); @@ -75,6 +76,7 @@ define([ imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); imagePreview.handleKeyDown(elementMock); expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + $.fn.get = originMock; }); }); From 00317ef8f28a89c2ad7e5bf23d47beca8d9534ac Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Thu, 30 Jan 2020 17:44:47 +0530 Subject: [PATCH 372/666] Static tests fix --- .../base/templates/product/price/tier_prices.phtml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 403e342c215ea..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,7 +73,8 @@ $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, @@ -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": { From 700dbafdce11bd7dd023972bc6f31bae7a8f97d7 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 30 Jan 2020 15:07:22 +0200 Subject: [PATCH 373/666] MC-30639: PayPal's Payment Review orders status change to Processing on payment update failure --- app/code/Magento/Paypal/Model/Ipn.php | 29 ++++-- .../Magento/Paypal/Model/IpnTest.php | 61 ++++++++++++- .../Magento/Paypal/_files/ipn_failed.php | 17 ++++ ...er_express_with_invoice_payment_review.php | 88 +++++++++++++++++++ 4 files changed, 185 insertions(+), 10 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/_files/ipn_failed.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/_files/order_express_with_invoice_payment_review.php diff --git a/app/code/Magento/Paypal/Model/Ipn.php b/app/code/Magento/Paypal/Model/Ipn.php index 9107762c54b69..0d7d5518f9c7d 100644 --- a/app/code/Magento/Paypal/Model/Ipn.php +++ b/app/code/Magento/Paypal/Model/Ipn.php @@ -106,6 +106,7 @@ protected function _getConfig() $parameters = ['params' => [$methodCode, $order->getStoreId()]]; $this->_config = $this->_configFactory->create($parameters); if (!$this->_config->isMethodActive($methodCode) || !$this->_config->isMethodAvailable()) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception(sprintf('The "%s" method isn\'t available.', $methodCode)); } /** @link https://cms.paypal.com/cgi-bin/marketingweb?cmd=_render-content&content_ID= @@ -117,6 +118,7 @@ protected function _getConfig() } $receiver = $this->getRequestData('business') ?: $this->getRequestData('receiver_email'); if (strtolower($merchantEmail) != strtolower($receiver)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception( sprintf( 'The requested "%s" and the configured "%s" merchant emails don\'t match.', @@ -140,6 +142,7 @@ protected function _getOrder() $incrementId = $this->getRequestData('invoice'); $this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId); if (!$this->_order->getId()) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception(sprintf('The "%s" order ID is incorrect. Verify the ID and try again.', $incrementId)); } return $this->_order; @@ -245,8 +248,11 @@ protected function _registerTransaction() break; // customer attempted to pay via bank account, but failed case Info::PAYMENTSTATUS_FAILED: - // cancel order - $this->_registerPaymentFailure(); + if ($this->_order->getState() === \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW) { + $this->_registerPaymentDenial(); + } else { + $this->_registerPaymentFailure(); + } break; // payment was obtained, but money were not captured yet case Info::PAYMENTSTATUS_PENDING: @@ -270,6 +276,7 @@ protected function _registerTransaction() $this->_registerPaymentVoid(); break; default: + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception("The '{$paymentStatus}' payment status couldn't be handled."); } } @@ -322,11 +329,12 @@ protected function _registerPaymentDenial() { try { $this->_importPaymentInformation(); - $this->_order->getPayment() - ->setTransactionId($this->getRequestData('txn_id')) - ->setNotificationResult(true) - ->setIsTransactionClosed(true) - ->deny(false); + $payment = $this->_order->getPayment(); + $payment->setTransactionId($this->getRequestData('txn_id')); + $payment->setPreparedMessage($this->_createIpnComment('')); + $payment->setNotificationResult(true); + $payment->setIsTransactionClosed(true); + $payment->deny(false); $this->_order->save(); } catch (LocalizedException $e) { if ($e->getMessage() != __('We cannot cancel this order.')) { @@ -360,6 +368,7 @@ public function _registerPaymentPending() return; } if ('order' === $reason) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new Exception('The "order" authorizations aren\'t implemented.'); } // case when was placed using PayPal standard @@ -501,6 +510,7 @@ protected function _registerPaymentVoid() /** * Map payment information from IPN to payment object + * * Returns true if there were changes in information * * @return bool @@ -537,8 +547,10 @@ protected function _importPaymentInformation() // collect fraud filters $fraudFilters = []; - for ($i = 1; $value = $this->getRequestData("fraud_management_pending_filters_{$i}"); $i++) { + $index = 1; + while ($value = $this->getRequestData("fraud_management_pending_filters_{$index}")) { $fraudFilters[] = $value; + $index++; } if ($fraudFilters) { $from[Info::FRAUD_FILTERS] = $fraudFilters; @@ -568,6 +580,7 @@ protected function _importPaymentInformation() /** * Generate an "IPN" comment with additional explanation. + * * Returns the generated comment or order status history object * * @param string $comment diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php index 1a22ea947f85a..1877e1faaec67 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php @@ -5,10 +5,13 @@ */ namespace Magento\Paypal\Model; -use Magento\Paypal\Model\IpnFactory; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\Order\Invoice; +use Magento\TestFramework\Helper\Bootstrap; /** * @magentoAppArea frontend @@ -22,7 +25,7 @@ class IpnTest extends \PHPUnit\Framework\TestCase protected function setUp() { - $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->_objectManager = Bootstrap::getObjectManager(); } /** @@ -158,6 +161,39 @@ public function testProcessIpnRequestRestRefund() $this->assertEmpty($order->getTotalOfflineRefunded()); } + /** + * Verifies canceling an order that was in payment review state by PayPal Express IPN message service. + * + * @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_payment_review.php + * @magentoConfigFixture current_store payment/paypal_express/active 1 + * @magentoConfigFixture current_store paypal/general/merchant_country US + */ + public function testProcessIpnRequestWithFailedStatus() + { + $ipnData = require __DIR__ . '/../_files/ipn_failed.php'; + + /** @var IpnFactory $ipnFactory */ + $ipnFactory = $this->_objectManager->create(IpnFactory::class); + $ipnModel = $ipnFactory->create( + [ + 'data' => $ipnData, + 'curlFactory' => $this->_createMockedHttpAdapter() + ] + ); + + $ipnModel->processIpnRequest(); + + $order = $this->getOrder($ipnData['invoice']); + $invoiceItems = $order->getInvoiceCollection() + ->getItems(); + /** @var Invoice $invoice */ + $invoice = array_pop($invoiceItems); + $invoice->getState(); + + $this->assertEquals(Order::STATE_CANCELED, $order->getState()); + $this->assertEquals(Invoice::STATE_CANCELED, $invoice->getState()); + } + /** * Test processIpnRequest() currency check for paypal_express and paypal_standard payment methods * @@ -224,4 +260,25 @@ protected function _createMockedHttpAdapter() $factory->expects($this->once())->method('create')->with()->will($this->returnValue($adapter)); return $factory; } + + /** + * Get stored order. + * + * @param string $incrementId + * @return OrderInterface + */ + private function getOrder(string $incrementId) + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter(OrderInterface::INCREMENT_ID, $incrementId) + ->create(); + + $orderRepository = $this->_objectManager->get(OrderRepositoryInterface::class); + $orders = $orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + return array_pop($orders); + } } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn_failed.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn_failed.php new file mode 100644 index 0000000000000..cf1822c9a1a52 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn_failed.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +return [ + 'invoice' => '100000002', + 'payment_status' => 'Failed', + 'receiver_email' => 'merchant_2012050718_biz@example.com', + 'parent_txn_id' => '84J11393WC835693U', + 'payer_status' => 'verified', + 'payment_type' => 'instant', + 'txn_id' => '1P566839F9694230H', + 'txn_type' => 'cart' +]; diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express_with_invoice_payment_review.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express_with_invoice_payment_review.php new file mode 100644 index 0000000000000..eb6654b274ba7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express_with_invoice_payment_review.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\DB\Transaction; +use Magento\Paypal\Model\Config; +use Magento\Sales\Api\InvoiceManagementInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Item; +use Magento\Sales\Model\Order\Address; +use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Service\InvoiceService; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../../Magento/Catalog/_files/product_simple.php'; + +$objectManager = Bootstrap::getObjectManager(); + +$addressData = include __DIR__ . '/address_data.php'; +$billingAddress = $objectManager->create( + Address::class, + ['data' => $addressData] +); +$billingAddress->setAddressType('billing'); +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +$payment = $objectManager->create(Payment::class); +$payment->setMethod(Config::METHOD_WPP_EXPRESS); + +/** @var Item $orderItem */ +$orderItem = $objectManager->create(Item::class); +$orderItem->setProductId($product->getId())->setQtyOrdered(1); +$orderItem->setBasePrice($product->getPrice()); +$orderItem->setPrice($product->getPrice()); +$orderItem->setRowTotal($product->getPrice()); +$orderItem->setRowTotalInclTax($product->getPrice()); +$orderItem->setBaseRowTotal($product->getPrice()); +$orderItem->setBaseRowTotalInclTax($product->getPrice()); +$orderItem->setBaseRowInvoiced($product->getPrice()); +$orderItem->setProductType('simple'); + +$itemsAmount = $product->getPrice(); +$shippingAmount = 20; +$totalAmount = $itemsAmount + $shippingAmount; + +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setCustomerEmail('co@co.co') + ->setIncrementId('100000002') + ->addItem($orderItem) + ->setSubtotal($itemsAmount) + ->setBaseSubtotal($itemsAmount) + ->setBaseGrandTotal($totalAmount) + ->setGrandTotal($totalAmount) + ->setBaseCurrencyCode('USD') + ->setCustomerIsGuest(true) + ->setStoreId(1) + ->setEmailSent(true) + ->setState(Order::STATE_PAYMENT_REVIEW) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setBaseTotalPaid($totalAmount) + ->setTotalPaid($totalAmount) + ->setData('base_to_global_rate', 1) + ->setData('base_to_order_rate', 1) + ->setData('shipping_amount', $shippingAmount) + ->setData('base_shipping_amount', $shippingAmount) + ->setPayment($payment); + +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +$orderRepository->save($order); + +/** @var InvoiceService $invoiceService */ +$invoiceService = $objectManager->create(InvoiceManagementInterface::class); + +/** @var Transaction $transaction */ +$transaction = $objectManager->create(Transaction::class); + +$invoice = $invoiceService->prepareInvoice($order, [$orderItem->getId() => 1]); +$invoice->register(); + +$transaction->addObject($invoice)->addObject($order)->save(); From 711895a6e866e1b996e82d51520984587179baeb Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 30 Jan 2020 15:13:09 +0200 Subject: [PATCH 374/666] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- .../Test/Mftf/Section/StorefrontCategoryMainSection.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index e6fc804fcf90c..82b622fbac818 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -17,9 +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"/> - <element name="addToWishListIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.towishlist"/> - <element name="addToCompareIconProductInfoHover" type="button" selector=".product-item-info:hover a.action.tocompare"/> + <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"/> @@ -30,7 +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="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//..//..//span[contains(@class, 'price')]" parameterized="true"/> + <element name="productPriceByName" type="text" selector="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//parent::strong//parent::div//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"/> From 0173e341fd66a8c58c25da2396f7678109a585da Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 16:34:57 +0200 Subject: [PATCH 375/666] Cover changes with integration test --- .../Block/Adminhtml/Edit/Tab/CartTest.php | 92 +++++++++++++++++-- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php index 2152d70c13d5e..90febc0d448ba 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php @@ -5,7 +5,13 @@ */ namespace Magento\Customer\Block\Adminhtml\Edit\Tab; +use Magento\Backend\Block\Template\Context; +use Magento\Backend\Model\Session\Quote as SessionQuote; use Magento\Customer\Controller\RegistryConstants; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Quote\Model\Quote; +use Magento\Store\Model\StoreManagerInterface; /** * Magento\Customer\Block\Adminhtml\Edit\Tab\Cart @@ -16,21 +22,34 @@ class CartTest extends \PHPUnit\Framework\TestCase { const CUSTOMER_ID_VALUE = 1234; - /** @var \Magento\Backend\Block\Template\Context */ + /** + * @var Context + */ private $_context; - /** @var \Magento\Framework\Registry */ + /** + * @var Registry + */ private $_coreRegistry; - /** @var \Magento\Store\Model\StoreManagerInterface */ + /** + * @var StoreManagerInterface + */ private $_storeManager; - /** @var Cart */ + /** + * @var Cart + */ private $_block; - /** @var \Magento\Framework\ObjectManagerInterface */ + /** + * @var ObjectManagerInterface + */ private $_objectManager; + /** + * @inheritdoc + */ public function setUp() { $this->_objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -53,22 +72,65 @@ public function setUp() ); } + /** + * @inheritdoc + */ public function tearDown() { $this->_coreRegistry->unregister(RegistryConstants::CURRENT_CUSTOMER_ID); } - public function testGetCustomerId() + /** + * Verify Grid with quote items + * + * @magentoDataFixture Magento/Sales/_files/quote_with_two_products_and_customer.php + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoAppIsolation enabled + * @magentoDbIsolation disabled + * @return void + */ + public function testVerifyCollectionWithQuote(): void + { + $session = $this->_objectManager->create(SessionQuote::class); + $session->setCustomerId(self::CUSTOMER_ID_VALUE); + $quoteFixture = $this->_objectManager->create(Quote::class); + $quoteFixture->load('test01', 'reserved_order_id'); + $quoteFixture->setCustomerIsGuest(false) + ->setCustomerId(self::CUSTOMER_ID_VALUE) + ->save(); + $html = $this->_block->toHtml(); + $this->assertNotContains( + "We couldn't find any records", + $this->_block->getGridParentHtml() + ); + } + + /** + * Verify Customer id + * + * @return void + */ + public function testGetCustomerId(): void { $this->assertEquals(self::CUSTOMER_ID_VALUE, $this->_block->getCustomerId()); } - public function testGetGridUrl() + /** + * Verify get grid url + * + * @return void + */ + public function testGetGridUrl(): void { $this->assertContains('/backend/customer/index/cart', $this->_block->getGridUrl()); } - public function testGetGridParentHtml() + /** + * Verify grid parent html + * + * @return void + */ + public function testGetGridParentHtml(): void { $this->_block = $this->_objectManager->get( \Magento\Framework\View\LayoutInterface::class @@ -87,14 +149,24 @@ public function testGetGridParentHtml() ); } - public function testGetRowUrl() + /** + * Verify row url + * + * @return void + */ + public function testGetRowUrl(): void { $row = new \Magento\Framework\DataObject(); $row->setProductId(1); $this->assertContains('/backend/catalog/product/edit/id/1', $this->_block->getRowUrl($row)); } - public function testGetHtml() + /** + * Verify get html + * + * @return void + */ + public function testGetHtml(): void { $html = $this->_block->toHtml(); $this->assertContains("<div id=\"customer_cart_grid\"", $html); From 79963bb6e690de198aa530d2d79d6ec725eb374a Mon Sep 17 00:00:00 2001 From: Dmitriy Kogut <kogut.dmitriy@gmail.com> Date: Thu, 30 Jan 2020 18:22:35 +0200 Subject: [PATCH 376/666] MC-24243: [MFTF test] Automate by MFTF test MC-27569 "Storefront product grid UI updates on Desktop" --- .../Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml | 2 +- ...frontAddToWishListIconIsClickableForGuestUserActionGroup.xml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 82b622fbac818..6b67f5609f7f0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -30,7 +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="//div[contains(@class, 'product-item-info')]//a[contains(text(), '{{productName}}')]//parent::strong//parent::div//span[contains(@class, 'price')]" parameterized="true"/> + <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/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml index 6d2bda0cb9e0b..690b6b8bc2b59 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/ActionGroup/AssertStorefrontAddToWishListIconIsClickableForGuestUserActionGroup.xml @@ -15,7 +15,6 @@ <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> <click selector="{{StorefrontCategoryMainSection.addToWishListIconProductInfoHover}}" stepKey="clickOnAddToWishListIcon"/> - <waitForPageLoad stepKey="waitForCustomerSignInPageLoad"/> <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"/> From 9bb416f4c625af4b9059d994fed3a74d1f6b9340 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Thu, 30 Jan 2020 19:16:40 +0200 Subject: [PATCH 377/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Fixed Unit tests. --- .../Model/Export/MetadataProviderTest.php | 122 +++++++++++++----- 1 file changed, 91 insertions(+), 31 deletions(-) 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..96bf43f14aa71 100755 --- a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php @@ -8,12 +8,12 @@ use Magento\Framework\Api\Search\DocumentInterface; 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\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; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -76,8 +76,10 @@ protected function setUp() /** * @param array $columnLabels * @param array $expected + * * @return void * @dataProvider getColumnsDataProvider + * @throws \Exception */ public function testGetHeaders(array $columnLabels, array $expected): void { @@ -156,11 +158,11 @@ protected function prepareColumns( $component->expects($this->any()) ->method('getName') ->willReturn($componentName); - $component->expects($this->once()) + $component->expects($this->atLeastOnce()) ->method('getChildComponents') ->willReturn([$columns]); - $columns->expects($this->once()) + $columns->expects($this->atLeastOnce()) ->method('getChildComponents') ->willReturn([$column, $columnActions]); @@ -267,52 +269,110 @@ public function getRowDataProvider() * @param string $filter * @param array $options * @param array $expected + * * @dataProvider getOptionsDataProvider + * @throws \Magento\Framework\Exception\LocalizedException */ public function testGetOptions($filter, $options, $expected) { + $component = $this->prepareColumnsWithOptions($filter, $options); + + $this->filter->expects($this->exactly(2)) + ->method('getComponent') + ->willReturn($component); + + $result = $this->model->getOptions(); + $this->assertTrue(is_array($result)); + $this->assertCount(1, $result); + $this->assertEquals($expected, $result); + } + + /** + * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected function prepareColumnsWithOptions(string $filter, array $options) + { + /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $component */ $component = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + ->getMockForAbstractClass(); - $childComponent = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + $listingTopComponent = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) + ->getMockForAbstractClass(); $filters = $this->getMockBuilder(\Magento\Ui\Component\Filters::class) - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); - $select = $this->getMockBuilder(\Magento\Ui\Component\Filters\Type\Select::class) - ->disableOriginalConstructor() - ->getMock(); + /** @var Columns|\PHPUnit_Framework_MockObject_MockObject $columns */ + $columns = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns::class) + ->disableOriginalConstructor() + ->getMock(); - $this->filter->expects($this->once()) - ->method('getComponent') - ->willReturn($component); + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $column */ + $column = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var Column|\PHPUnit_Framework_MockObject_MockObject $columnActions */ + $columnActions = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) + ->disableOriginalConstructor() + ->getMock(); - $component->expects($this->once()) - ->method('getChildComponents') - ->willReturn(['listing_top' => $childComponent]); + $component->expects($this->any()) + ->method('getName') + ->willReturn('columns_component_name'); + $component->expects($this->atLeastOnce()) + ->method('getChildComponents') + ->willReturn(['columns' => $columns, 'listing_top' => $listingTopComponent]); - $childComponent->expects($this->once()) - ->method('getChildComponents') - ->willReturn([$filters]); + $listingTopComponent->expects($this->once()) + ->method('getChildComponents') + ->willReturn([$filters]); + + $select = $this->getMockBuilder(\Magento\Ui\Component\Filters\Type\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($options); - $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'); + $column->expects($this->any()) + ->method('getData') + ->willReturnMap( + [ + ['config/label', null, 'column_label'], + ['config/dataType', null, 'data_type'], + ] + ); + + $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; } /** From cd24e419741b7834d2012be7c039fd01e57e82e7 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Thu, 30 Jan 2020 19:17:23 +0200 Subject: [PATCH 378/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Unit tests code reformatting. --- .../Model/Export/MetadataProviderTest.php | 181 ++++++++++-------- 1 file changed, 97 insertions(+), 84 deletions(-) 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 96bf43f14aa71..6741daff92e28 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,29 @@ * 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\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 PHPUnit\Framework\TestCase; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class MetadataProviderTest extends \PHPUnit\Framework\TestCase +class MetadataProviderTest extends TestCase { /** * @var MetadataProvider @@ -45,25 +52,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, @@ -99,12 +106,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']], ]; } @@ -128,6 +135,7 @@ public function testGetFields() * @param string $columnLabel * @param string $columnActionsName * @param string $columnActionsLabel + * * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject */ protected function prepareColumns( @@ -138,57 +146,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); + ->method('getName') + ->willReturn($componentName); $component->expects($this->atLeastOnce()) - ->method('getChildComponents') - ->willReturn([$columns]); + ->method('getChildComponents') + ->willReturn([$columns]); $columns->expects($this->atLeastOnce()) - ->method('getChildComponents') - ->willReturn([$column, $columnActions]); + ->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; } @@ -198,25 +206,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)); @@ -271,15 +280,15 @@ public function getRowDataProvider() * @param array $expected * * @dataProvider getOptionsDataProvider - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function testGetOptions($filter, $options, $expected) { $component = $this->prepareColumnsWithOptions($filter, $options); $this->filter->expects($this->exactly(2)) - ->method('getComponent') - ->willReturn($component); + ->method('getComponent') + ->willReturn($component); $result = $this->model->getOptions(); $this->assertTrue(is_array($result)); @@ -288,32 +297,35 @@ public function testGetOptions($filter, $options, $expected) } /** + * @param string $filter + * @param array $options + * * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject */ protected function prepareColumnsWithOptions(string $filter, array $options) { /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $component */ - $component = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) + $component = $this->getMockBuilder(UiComponentInterface::class) ->getMockForAbstractClass(); - $listingTopComponent = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponentInterface::class) - ->getMockForAbstractClass(); + $listingTopComponent = $this->getMockBuilder(UiComponentInterface::class) + ->getMockForAbstractClass(); - $filters = $this->getMockBuilder(\Magento\Ui\Component\Filters::class) + $filters = $this->getMockBuilder(Filters::class) ->disableOriginalConstructor() ->getMock(); /** @var Columns|\PHPUnit_Framework_MockObject_MockObject $columns */ - $columns = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns::class) + $columns = $this->getMockBuilder(Columns::class) ->disableOriginalConstructor() ->getMock(); /** @var Column|\PHPUnit_Framework_MockObject_MockObject $column */ - $column = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) + $column = $this->getMockBuilder(Column::class) ->disableOriginalConstructor() ->getMock(); /** @var Column|\PHPUnit_Framework_MockObject_MockObject $columnActions */ - $columnActions = $this->getMockBuilder(\Magento\Ui\Component\Listing\Columns\Column::class) + $columnActions = $this->getMockBuilder(Column::class) ->disableOriginalConstructor() ->getMock(); @@ -328,7 +340,7 @@ protected function prepareColumnsWithOptions(string $filter, array $options) ->method('getChildComponents') ->willReturn([$filters]); - $select = $this->getMockBuilder(\Magento\Ui\Component\Filters\Type\Select::class) + $select = $this->getMockBuilder(Select::class) ->disableOriginalConstructor() ->getMock(); @@ -446,6 +458,7 @@ public function getOptionsDataProvider() * * @param string $fieldValue * @param string $expected + * * @dataProvider convertDateProvider * @covers \Magento\Ui\Model\Export\MetadataProvider::convertDate() */ @@ -453,22 +466,22 @@ 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); } From 6b434ba7a4cc581cb2e83f183959a7c7e0a98430 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Thu, 30 Jan 2020 19:41:39 +0200 Subject: [PATCH 379/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Implemented Unit tests coverage. --- .../Ui/Model/Export/MetadataProvider.php | 2 +- .../Model/Export/MetadataProviderTest.php | 65 +++++++++++++++---- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index b47b4c0f57d14..dd0bc20255d9a 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -260,7 +260,7 @@ protected function getColumnOptions(): array $optionSource = $columnComponent->getData('options'); $optionsArray = $optionSource instanceof OptionSourceInterface ? $optionSource->toOptionArray() : $optionSource; - $options[$columnComponent->getName()] = $this->getOptionsArray($optionsArray); + $options[$columnComponent->getName()] = $this->getOptionsArray($optionsArray ?: []); } } 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 6741daff92e28..1d581e84dbdf0 100755 --- a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php @@ -8,6 +8,7 @@ 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; @@ -276,15 +277,16 @@ public function getRowDataProvider() /** * @param string $filter - * @param array $options + * @param array $filterOptions + * @param array $columnsOptions * @param array $expected * - * @dataProvider getOptionsDataProvider * @throws LocalizedException + * @dataProvider getOptionsDataProvider */ - public function testGetOptions($filter, $options, $expected) + public function testGetOptions(string $filter, array $filterOptions, array $columnsOptions, array $expected) { - $component = $this->prepareColumnsWithOptions($filter, $options); + $component = $this->prepareColumnsWithOptions($filter, $filterOptions, $columnsOptions); $this->filter->expects($this->exactly(2)) ->method('getComponent') @@ -292,17 +294,19 @@ public function testGetOptions($filter, $options, $expected) $result = $this->model->getOptions(); $this->assertTrue(is_array($result)); - $this->assertCount(1, $result); + $this->assertCount(2, $result); $this->assertEquals($expected, $result); } /** * @param string $filter - * @param array $options + * @param array $filterOptions + * + * @param array $columnsOptions * * @return UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected function prepareColumnsWithOptions(string $filter, array $options) + protected function prepareColumnsWithOptions(string $filter, array $filterOptions, array $columnsOptions) { /** @var UiComponentInterface|\PHPUnit_Framework_MockObject_MockObject $component */ $component = $this->getMockBuilder(UiComponentInterface::class) @@ -354,7 +358,7 @@ protected function prepareColumnsWithOptions(string $filter, array $options) $select->expects($this->any()) ->method('getData') ->with('config/options') - ->willReturn($options); + ->willReturn($filterOptions); $columns->expects($this->atLeastOnce()) ->method('getChildComponents') @@ -363,15 +367,28 @@ protected function prepareColumnsWithOptions(string $filter, array $options) $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'); @@ -395,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', @@ -405,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' => [ [ @@ -424,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' => [ [ @@ -444,10 +484,12 @@ public function getOptionsDataProvider() 'label' => 'label_1', ] ], + 'columnsOptions' => [], 'expected' => [ 'filter_name' => [ 'value_3' => 'label_1label_2label_3', ], + 'column_name' => [] ], ], ]; @@ -461,6 +503,7 @@ public function getOptionsDataProvider() * * @dataProvider convertDateProvider * @covers \Magento\Ui\Model\Export\MetadataProvider::convertDate() + * @throws \Exception */ public function testConvertDate($fieldValue, $expected) { From a3dc4505db1ce7f634ede1a32a0cc5fe86b60027 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 30 Jan 2020 17:01:34 +0200 Subject: [PATCH 380/666] Add more cases --- .../Block/Adminhtml/Edit/Tab/CartTest.php | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php index 90febc0d448ba..34e28838d0e0d 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Block/Adminhtml/Edit/Tab/CartTest.php @@ -17,6 +17,7 @@ * Magento\Customer\Block\Adminhtml\Edit\Tab\Cart * * @magentoAppArea adminhtml + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CartTest extends \PHPUnit\Framework\TestCase { @@ -28,7 +29,7 @@ class CartTest extends \PHPUnit\Framework\TestCase private $_context; /** - * @var Registry + * @var Registry */ private $_coreRegistry; @@ -38,7 +39,7 @@ class CartTest extends \PHPUnit\Framework\TestCase private $_storeManager; /** - * @var Cart + * @var Cart */ private $_block; @@ -85,24 +86,55 @@ public function tearDown() * * @magentoDataFixture Magento/Sales/_files/quote_with_two_products_and_customer.php * @magentoDataFixture Magento/Customer/_files/customer.php - * @magentoAppIsolation enabled - * @magentoDbIsolation disabled + * @dataProvider getQuoteDataProvider + * + * @param int $customerId + * @param bool $guest + * @param bool $contains * @return void */ - public function testVerifyCollectionWithQuote(): void + public function testVerifyCollectionWithQuote(int $customerId, bool $guest, bool $contains): void { $session = $this->_objectManager->create(SessionQuote::class); - $session->setCustomerId(self::CUSTOMER_ID_VALUE); + $session->setCustomerId($customerId); $quoteFixture = $this->_objectManager->create(Quote::class); $quoteFixture->load('test01', 'reserved_order_id'); - $quoteFixture->setCustomerIsGuest(false) - ->setCustomerId(self::CUSTOMER_ID_VALUE) + $quoteFixture->setCustomerIsGuest($guest) + ->setCustomerId($customerId) ->save(); - $html = $this->_block->toHtml(); - $this->assertNotContains( - "We couldn't find any records", - $this->_block->getGridParentHtml() - ); + $this->_block->toHtml(); + if ($contains) { + $this->assertContains( + "We couldn't find any records", + $this->_block->getGridParentHtml() + ); + } else { + $this->assertNotContains( + "We couldn't find any records", + $this->_block->getGridParentHtml() + ); + } + } + + /** + * Data provider for withQuoteTest + * + * @return array + */ + public function getQuoteDataProvider(): array + { + return [ + [ + 6, + false, + true + ], + [ + self::CUSTOMER_ID_VALUE, + true, + false + ], + ]; } /** From 292905baa80f5567209a8e6322c86b2bb3a874ff Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 30 Jan 2020 18:08:30 -0600 Subject: [PATCH 381/666] MC-30908: \Magento\Test\Php\LiveCodeTest checks added files incorrectly --- dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } ); From 996406f506557ecb49ae0951ca1d9c20043a2b92 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 31 Jan 2020 08:56:07 +0200 Subject: [PATCH 382/666] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...logPriceRuleAddSkuConditionActionGroup.xml | 28 +++++ ...ConfigurableWithCatalogRuleAppliedTest.xml | 105 +++++++++--------- 2 files changed, 83 insertions(+), 50 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.xml new file mode 100644 index 0000000000000..2c4e3ddb648e0 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleAddSkuConditionActionGroup.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="AdminCatalogPriceRuleAddSkuConditionActionGroup"> + <annotations> + <description>Create new product SKU based condition in Catalog Price Rule form.</description> + </annotations> + <arguments> + <argument name="productSku" type="string" defaultValue="{{ApiSimpleTwo.sku}}"/> + </arguments> + + <conditionalClick selector="{{AdminNewCatalogPriceRule.conditionsTabTitle}}" dependentSelector="{{AdminNewCatalogPriceRule.conditionsTabBody}}" visible="false" stepKey="openConditionsSectionIfNeeded"/> + <scrollTo selector="{{AdminNewCatalogPriceRule.conditionsTabTitle}}" stepKey="scrollToConditionsFieldset"/> + <waitForElementVisible selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="waitForNewConditionButton"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.newCondition}}" stepKey="clickAddNewConditionButton"/> + <selectOption selector="{{AdminNewCatalogPriceRuleConditions.conditionSelect('1')}}" userInput="Magento\CatalogRule\Model\Rule\Condition\Product|sku" stepKey="selectConditionTypeSku"/> + <waitForPageLoad stepKey="waitConditionFormRefresh"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.targetEllipsis('1')}}" stepKey="clickEllipsis"/> + <fillField selector="{{AdminNewCatalogPriceRuleConditions.targetInput('1', '1')}}" userInput="{{productSku}}" stepKey="fillProductSku"/> + <click selector="{{AdminNewCatalogPriceRuleConditions.applyButton('1', '1')}}" stepKey="clickApply"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 7828478bc963e..02700b2fd7c85 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -8,15 +8,18 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest"> + <test name="StorefrontCheckSortingByPriceForConfigurableWithCatalogRuleAppliedTest"> <annotations> <features value="ConfigurableProduct"/> - <stories value="View soting by price in storefront"/> - <title value="Sorting by price for Configurable with Catalog Rule applied"/> + <stories value="Check sorting by price on storefront"/> + <title value="Check sorting by price for Configurable product with Catalog Rule applied"/> <description value="Sort by price should be correct if the apply Catalog Rule to child product of configurable product"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-69988"/> - <group value="configurable_product"/> + <testCaseId value="MC-11926"/> + <useCaseId value="MAGETWO-66688"/> + <group value="catalog"/> + <group value="catalogRule"/> + <group value="configurableProduct"/> </annotations> <before> <createData entity="ApiCategory" stepKey="createCategory"/> @@ -28,63 +31,63 @@ <requiredEntity createDataKey="createCategory"/> <field key="price">10.00</field> </createData> - <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <createData entity="ApiConfigurableProduct" stepKey="createConfigurableProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> - <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigurableProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigurableProductAttributeOption1"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> - <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption2" stepKey="createConfigurableProductAttributeOption2"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> - <createData entity="productAttributeOption3" stepKey="createConfigProductAttributeOption3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption3" stepKey="createConfigurableProductAttributeOption3"> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </createData> <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <getData entity="ProductAttributeOptionGetter" index="3" stepKey="getConfigAttributeOption3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> </getData> <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> <field key="price">15.00</field> </createData> <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption2"/> <field key="price">20.00</field> </createData> <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct3"> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption3"/> <field key="price">25.00</field> </createData> - <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigProductOption"> - <requiredEntity createDataKey="createConfigProduct"/> - <requiredEntity createDataKey="createConfigProductAttribute"/> + <createData entity="ConfigurableProductThreeOptions" stepKey="createConfigurableProductOption"> + <requiredEntity createDataKey="createConfigurableProduct"/> + <requiredEntity createDataKey="createConfigurableProductAttribute"/> <requiredEntity createDataKey="getConfigAttributeOption1"/> <requiredEntity createDataKey="getConfigAttributeOption2"/> <requiredEntity createDataKey="getConfigAttributeOption3"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild1"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct1"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild2"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> - <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild3"> - <requiredEntity createDataKey="createConfigProduct"/> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigurableProductAddChild3"> + <requiredEntity createDataKey="createConfigurableProduct"/> <requiredEntity createDataKey="createConfigChildProduct3"/> </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> @@ -95,8 +98,8 @@ <actionGroup ref="ChangeUseForPromoRuleConditionsProductAttributeActionGroup" stepKey="changeUseForPromoRuleConditionsProductAttributeToYes"> <argument name="option" value="Yes"/> </actionGroup> - <magentoCLI command="indexer:reindex" stepKey="reindex1"/> - <magentoCLI command="cache:flush" stepKey="flushCache1"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> + <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> </before> <after> @@ -106,8 +109,8 @@ <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> - <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> - <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigurableProductAttribute" stepKey="deleteConfigProductAttribute"/> <!--SKU Product Attribute is disable for Promo Rule Conditions--> <actionGroup ref="NavigateToEditProductAttributeActionGroup" stepKey="navigateToSkuProductAttribute"> @@ -116,7 +119,12 @@ <actionGroup ref="ChangeUseForPromoRuleConditionsProductAttributeActionGroup" stepKey="changeUseForPromoRuleConditionsProductAttributeToNo"> <argument name="option" value="No"/> </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- TODO: Remove this and change to CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <!-- Need reindex because creating new product attributes break some indices and this may affect other tests in testsuite --> + <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> </after> <!--Open category with products and Sort by price desc--> @@ -127,20 +135,24 @@ <argument name="sortBy" value="price"/> <argument name="sort" value="desc"/> </actionGroup> - <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct"/> + <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createConfigurableProduct.name$$" stepKey="seeConfigurableProduct"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct"/> <!--Create and apply catalog price rule--> - <actionGroup ref="NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup" stepKey="createCatalogPriceRule"> - <argument name="catalogRule" value="CatalogRuleByPercentWith96Amount" /> - <argument name="productSku" value="$$createConfigChildProduct3.sku$$" /> + <actionGroup ref="AdminOpenNewCatalogPriceRuleFormPageActionGroup" stepKey="startCreatingCatalogPriceRule"/> + <actionGroup ref="AdminCatalogPriceRuleFillMainInfoActionGroup" stepKey="fillMainInfoForCatalogPriceRule"> + <argument name="groups" value="'NOT LOGGED IN'"/> </actionGroup> - <actionGroup ref="SelectNotLoggedInCustomerGroupActionGroup" stepKey="selectNotLoggedInCustomerGroup"/> - <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules"/> - - <magentoCLI command="indexer:reindex" stepKey="reindex"/> - <magentoCLI command="cache:flush" stepKey="flushCache"/> + <actionGroup ref="AdminCatalogPriceRuleAddSkuConditionActionGroup" stepKey="addProductSkuBasedCondition"> + <argument name="productSku" value="$createConfigChildProduct3.sku$"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForCatalogPriceRule"> + <argument name="apply" value="{{CatalogRuleByPercentWith96Amount.simple_action}}"/> + <argument name="discountAmount" value="{{CatalogRuleByPercentWith96Amount.discount_amount}}"/> + </actionGroup> + <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> + <actionGroup ref="AdminReindexAndFlushCache" stepKey="reindexAndFlushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> @@ -152,13 +164,6 @@ </actionGroup> <see selector="{{StorefrontCategoryMainSection.lineProductName('1')}}" userInput="$$createSimpleProduct2.name$$" stepKey="seeSimpleProductTwo2"/> <see selector="{{StorefrontCategoryMainSection.lineProductName('2')}}" userInput="$$createSimpleProduct.name$$" stepKey="seeSimpleProduct2"/> - <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createConfigProduct.name$$" stepKey="seeConfigurableProduct2"/> - - <!-- Delete the rule --> - <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage"/> - <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule"> - <argument name="name" value="{{CatalogRuleByPercentWith96Amount.name}}"/> - <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> - </actionGroup> + <see selector="{{StorefrontCategoryMainSection.lineProductName('3')}}" userInput="$$createConfigurableProduct.name$$" stepKey="seeConfigurableProduct2"/> </test> </tests> From 3056027889eb89fb63341af79217d9ff34af17ec Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Fri, 31 Jan 2020 09:35:50 +0200 Subject: [PATCH 383/666] MC-30777: '1 record found' is shown on the product grid regardless of the number of displayed products --- .../Ui/Component/Listing/Columns/Websites.php | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php index 494b77724e5b7..c80b2663d1f69 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - declare(strict_types=1); namespace Magento\Catalog\Ui\Component\Listing\Columns; @@ -120,31 +119,32 @@ protected function applySorting() && !empty($sorting['direction']) && $sorting['field'] === $this->getName() ) { + /** @var \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection $collection */ $collection = $this->getContext()->getDataProvider()->getCollection(); - $collection - ->joinField( - 'websites_ids', - 'catalog_product_website', - 'website_id', - 'product_id=entity_id', - null, - 'left' - ) - ->joinTable( - 'store_website', - 'website_id = websites_ids', - ['name'], - null, - 'left' - ) - ->groupByAttribute('entity_id'); - $this->resourceHelper->addGroupConcatColumn( - $collection->getSelect(), - $this->websiteNames, - 'name' + + $select = $collection->getConnection()->select(); + $select->from( + ['cpw' => $collection->getTable('catalog_product_website')], + ['product_id'] + )->joinLeft( + ['sw' => $collection->getTable('store_website')], + 'cpw.website_id = sw.website_id', + [ + $this->websiteNames => new \Zend_Db_Expr( + 'GROUP_CONCAT(sw.name ORDER BY sw.website_id ASC SEPARATOR \',\')' + ) + ] + )->group( + 'cpw.product_id' ); - $collection->getSelect()->order($this->websiteNames . ' ' . $sorting['direction']); + $collection->getSelect()->joinLeft( + ['product_websites' => $select], + 'product_websites.product_id = e.entity_id', + [$this->websiteNames] + )->order( + 'product_websites.' . $this->websiteNames . ' ' . $sorting['direction'] + ); } } } From b1d99e54dd9d9ca0881db11c8e9ca6a04a50b268 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Fri, 31 Jan 2020 11:25:19 +0200 Subject: [PATCH 384/666] Cover test to change --- ...sales_email_order_creditmemo_renderers.xml | 5 +- .../Email/Items/CreditMemo/GroupedTest.php | 60 +++++++++++++++++ .../creditmemo_with_grouped_product.php | 36 ++++++++++ ...editmemo_with_grouped_product_rollback.php | 18 +++++ .../_files/order_with_grouped_product.php | 65 +++++++++++++++++++ .../order_with_grouped_product_rollback.php | 8 +++ 6 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/GroupedProduct/Block/Order/Email/Items/CreditMemo/GroupedTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_grouped_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/order_with_grouped_product_rollback.php 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 95fe2f37044c7..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,10 +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\CreditMemo\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/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/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_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'; From e6a3bee7dfbf17456e768a77d78e8e9a1b5bf133 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 11:30:41 +0100 Subject: [PATCH 385/666] #26607 Fix failing CI due to missing "createSimpleProductApi" --- app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 46bb6e527608f..91431820dd563 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -136,6 +136,7 @@ <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"> From 5be754b7d3de102cb9ec6ef2f43dbdbcb797540a Mon Sep 17 00:00:00 2001 From: Mateusz Krzeszowiak <mateusz.krzeszowiak@creativestyle.pl> Date: Thu, 28 Nov 2019 17:08:19 +0100 Subject: [PATCH 386/666] Add failing test and fix it --- .../view/frontend/web/js/section-config.js | 2 +- .../Customer/frontend/js/section-config.test.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/view/frontend/web/js/section-config.js b/app/code/Magento/Customer/view/frontend/web/js/section-config.js index 60482e5fee260..107a177d0832f 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/section-config.js +++ b/app/code/Magento/Customer/view/frontend/web/js/section-config.js @@ -50,7 +50,7 @@ define(['underscore'], function (_) { return route.indexOf(section) === 0; }); - return _.union(actions, sections['*']); + return _.union(_.toArray(actions), sections['*']); }, /** diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/section-config.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/section-config.test.js index 56ed546e28f8c..ef7222883b738 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/section-config.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Customer/frontend/js/section-config.test.js @@ -128,6 +128,21 @@ define(['squire'], function (Squire) { expect(obj.getAffectedSections('http://localhost.com/path')).toEqual(['all']); }); + + it('Ignores capitalization in parts of URL.', function () { + obj['Magento_Customer/js/section-config']({ + sections: { + 'path': [ + 'section' + ] + }, + baseUrls: [ + 'http://localhost.com/' + ] + }); + + expect(obj.getAffectedSections('http://localhost.com/PaTh')).toEqual(['section']); + }); }); describe('"filterClientSideSections" method', function () { From b29cdcd238ded56050308d54aa22df3bc7672a43 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 01:42:48 +0100 Subject: [PATCH 387/666] #26610 Fix failing CI due to invalid variable handler --- ...ngNewOptionsWithImagesAndPricesToConfigurableProductTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml index 86c4d0398b2cc..a70a62470ecbc 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminAddingNewOptionsWithImagesAndPricesToConfigurableProductTest.xml @@ -32,7 +32,7 @@ <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <actionGroup ref="DeleteProductActionGroup" stepKey="deleteProduct1"> - <argument name="productName" value="$$createConfigProductAttributeCreateConfigurableProduct.name$$"/> + <argument name="productName" value="$$createConfigProductCreateConfigurableProduct.name$$"/> </actionGroup> <actionGroup ref="logout" stepKey="logout"/> </after> From b117b0c9cba0e7664ce3961600acf992cb55a55a Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Fri, 31 Jan 2020 12:24:45 +0200 Subject: [PATCH 388/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Removed deprecated class. --- .../Order/Invoice/Grid/Collection.php | 6 -- .../Component/DataProvider/DocumentTest.php | 98 ------------------- .../Ui/Component/DataProvider/Document.php | 91 ----------------- .../Ui/Model/Export/MetadataProvider.php | 2 +- .../Model/Export/MetadataProviderTest.php | 2 +- 5 files changed, 2 insertions(+), 197 deletions(-) delete mode 100644 app/code/Magento/Sales/Test/Unit/Ui/Component/DataProvider/DocumentTest.php delete mode 100644 app/code/Magento/Sales/Ui/Component/DataProvider/Document.php 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 index 9c261fa31bc25..b73395780ac70 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php @@ -9,16 +9,10 @@ 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. * 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/Ui/Model/Export/MetadataProvider.php b/app/code/Magento/Ui/Model/Export/MetadataProvider.php index dd0bc20255d9a..59f3af18de451 100755 --- a/app/code/Magento/Ui/Model/Export/MetadataProvider.php +++ b/app/code/Magento/Ui/Model/Export/MetadataProvider.php @@ -174,7 +174,7 @@ public function getRowData(DocumentInterface $document, $fields, $options): arra if (isset($options[$column][$key])) { $row[] = $options[$column][$key]; } else { - $row[] = ''; + $row[] = $key; } } else { $row[] = $document->getCustomAttribute($column)->getValue(); 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 1d581e84dbdf0..1b86bc14c7df7 100755 --- a/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php +++ b/app/code/Magento/Ui/Test/Unit/Model/Export/MetadataProviderTest.php @@ -261,7 +261,7 @@ public function getRowDataProvider() ], ], 'expected' => [ - '', + 'key_2', ], ], [ From e26a536d1960253dfa2242b5793a6c805413a9ca Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 13:34:50 +0100 Subject: [PATCH 389/666] #26607 Additional changes that make Test more stable --- .../Magento/Catalog/Test/Mftf/Data/ProductData.xml | 2 +- .../ActionGroup/OpenCatalogPriceRuleActionGroup.xml | 1 + .../Mftf/Test/AdminReorderWithCatalogPriceTest.xml | 11 +++++------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 91431820dd563..b160d958f423b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -128,7 +128,7 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="SimpleProduct2" type="product"> - <data key="sku" unique="suffix">SimpleProduct</data> + <data key="sku" unique="suffix">simple-product</data> <data key="type_id">simple</data> <data key="attribute_set_id">4</data> <data key="name" unique="suffix">SimpleProduct</data> 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/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml index dc74e024b2629..f5489b82520f7 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceTest.xml @@ -20,10 +20,13 @@ <group value="catalogRule"/> </annotations> <before> - <!--Create the catalog price rule --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="CatalogRuleToPercent" stepKey="createCatalogRule"/> - <!--Create product--> <createData entity="SimpleProduct2" stepKey="createSimpleProductApi"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <!--Create order via API--> <createData entity="GuestCart" stepKey="createGuestCart"/> <createData entity="SimpleCartItem" stepKey="addCartItem"> @@ -36,8 +39,6 @@ <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> @@ -52,8 +53,6 @@ <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/> <actionGroup ref="logout" stepKey="logout"/> </after> - <!-- Login as admin --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <!--Open order page by Id--> <amOnPage url="{{AdminOrderPage.url($createGuestCart.return$)}}" stepKey="navigateToOrderPage"/> <waitForPageLoad stepKey="waitForCreatedOrderPage"/> From c13b83fd26c3368c8536995caf918f4372e56b52 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 13:42:30 +0100 Subject: [PATCH 390/666] #26612 Fix failure on Coupon Apply procedure when loading mask still on page --- .../Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml | 2 +- .../Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml index 7edc37d510266..5e13ce3e06e10 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml @@ -54,7 +54,7 @@ <argument name="shippingMethod" value="Flat Rate"/> </actionGroup> - <!-- Click Apply Discount Code: section is expanded. Input promo code, apply and see success message --> + <!-- Click Apply Discount Code: section is expanded. Input promo code, apply and see success message --> <actionGroup ref="StorefrontApplyDiscountCodeActionGroup" stepKey="applyCoupon"> <argument name="discountCode" value="$$createCouponForCartPriceRule.code$$"/> </actionGroup> diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml index 3cf96a8b3dc06..fadfadc8ee7cd 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/StorefrontApplyDiscountCodeActionGroup.xml @@ -16,6 +16,7 @@ <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"/> <see selector="{{DiscountSection.DiscountVerificationMsg}}" userInput="Your coupon was successfully applied" stepKey="assertDiscountApplyMessage"/> </actionGroup> </actionGroups> From 4a78ca5d3270009fe79e74431263e96acd7e8c83 Mon Sep 17 00:00:00 2001 From: Maksym Novik <novik.kor@gmail.com> Date: Fri, 31 Jan 2020 14:54:21 +0200 Subject: [PATCH 391/666] Grid Export rendered data is not reflecting in the exported File, Displayed ID instead of Rendered Label #25963. Removed deprecated class. --- .../Order/Invoice/Grid/Collection.php | 36 ------------------- app/code/Magento/Sales/etc/di.xml | 6 ++++ 2 files changed, 6 insertions(+), 36 deletions(-) delete mode 100644 app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php 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 b73395780ac70..0000000000000 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php +++ /dev/null @@ -1,36 +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 Psr\Log\LoggerInterface as Logger; - -class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult -{ - /** - * 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/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 9f705c1a674c1..4ae1482da65d1 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> From 98d319b3f5c9f170da5ffca234cac212973b3817 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 31 Jan 2020 15:10:24 +0200 Subject: [PATCH 392/666] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...ngByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 02700b2fd7c85..85f35703592c1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -99,7 +99,8 @@ <argument name="option" value="Yes"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> - <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </before> <after> @@ -122,9 +123,8 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllRules"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> - <!-- TODO: Remove this and change to CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> - <!-- Need reindex because creating new product attributes break some indices and this may affect other tests in testsuite --> - <magentoCLI command="indexer:reindex" stepKey="reindexIndices"/> + <!-- TODO: Replace this with CliRunReindexUsingCronJobsActionGroup after MC-29943 delivered--> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product" stepKey="reindexIndices"/> </after> <!--Open category with products and Sort by price desc--> From 92aee111d387a8deda1c0fa3c6087f5b108d1c9b Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Fri, 31 Jan 2020 15:19:45 +0200 Subject: [PATCH 393/666] MC-30734: Admin: sort by Attribute set on product page doesn't work as expected --- .../Listing/Columns/AttributeSetId.php | 39 +++++++++++++++++++ .../ui_component/product_listing.xml | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Ui/Component/Listing/Columns/AttributeSetId.php diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/AttributeSetId.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/AttributeSetId.php new file mode 100644 index 0000000000000..5e9f7ba065be7 --- /dev/null +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/AttributeSetId.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Ui\Component\Listing\Columns; + +/** + * Attribute set listing column component + */ +class AttributeSetId extends \Magento\Ui\Component\Listing\Columns\Column +{ + /** + * @inheritDoc + */ + protected function applySorting() + { + $sorting = $this->getContext()->getRequestParam('sorting'); + $isSortable = $this->getData('config/sortable'); + if ($isSortable !== false + && !empty($sorting['field']) + && !empty($sorting['direction']) + && $sorting['field'] === $this->getName() + ) { + $collection = $this->getContext()->getDataProvider()->getCollection(); + $collection->joinField( + 'attribute_set', + 'eav_attribute_set', + 'attribute_set_name', + 'attribute_set_id=attribute_set_id', + null, + 'left' + ); + $collection->getSelect()->order('attribute_set_name ' . $sorting['direction']); + } + } +} diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml index d2d6f098125ce..88bb578712056 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_listing.xml @@ -144,7 +144,7 @@ <label translate="true">Type</label> </settings> </column> - <column name="attribute_set_id" component="Magento_Ui/js/grid/columns/select" sortOrder="50"> + <column name="attribute_set_id" class="Magento\Catalog\Ui\Component\Listing\Columns\AttributeSetId" component="Magento_Ui/js/grid/columns/select" sortOrder="50"> <settings> <options class="Magento\Catalog\Model\Product\AttributeSet\Options"/> <filter>select</filter> From 695804766e5ba2a7bd2a75252d5bf6ca6cdf37c0 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 31 Jan 2020 15:51:59 +0200 Subject: [PATCH 394/666] Unit Test for Magento\LayeredNavigation\Observer\Edit\Tab\Front\ProductAttributeFormBuildFrontTabObserver --- ...AttributeFormBuildFrontTabObserverTest.php | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 app/code/Magento/LayeredNavigation/Test/Unit/Observer/Edit/Tab/Front/ProductAttributeFormBuildFrontTabObserverTest.php 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..ec9d113665850 --- /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\ProductAttributeFormBuildFrontTabObserverTest; + +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() + { + $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() + { + $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() + { + $this->moduleManagerMock->expects($this->once()) + ->method('isOutputEnabled') + ->with('Magento_LayeredNavigation') + ->willReturn(true); + + $fieldsetMock = $this->createMock(Fieldset::class); + $fieldsetMock->expects(self::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); + } +} From a183437b8c95f9487d5c815605ac7c89e7fa2a95 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 31 Jan 2020 16:03:49 +0200 Subject: [PATCH 395/666] Code cleaning --- .../Observer/CheckoutCartAddProductObserverTest.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php index 02bdbdf794ac6..d9a75c96d4304 100644 --- a/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php +++ b/app/code/Magento/Reports/Test/Unit/Observer/CheckoutCartAddProductObserverTest.php @@ -20,7 +20,7 @@ use PHPUnit\Framework\TestCase; /** - * Unit Test for @see CheckoutCartAddProductObserver + * Unit Test for \Magento\Reports\Observer\CheckoutCartAddProductObserver */ class CheckoutCartAddProductObserverTest extends TestCase { @@ -84,7 +84,7 @@ protected function setUp() /** * The case when event has to be successfully saved */ - public function testExecute() + public function testExecuteExpectsSaveCalledWhenNewProductAdded() { $this->configureMocksWhenReportsEnabled(); $this->quoteItemMock->expects($this->once()) @@ -94,8 +94,7 @@ public function testExecute() ->method('getParentItem') ->willReturn(null); - $this->eventSaverMock->expects($this->once()) - ->method('save'); + $this->eventSaverMock->expects($this->once())->method('save'); $this->observer->execute($this->eventObserverMock); } @@ -159,8 +158,7 @@ private function configureMocksWhenReportsEnabled() */ private function checkOriginalMethodIsNeverExecuted() { - $this->eventSaverMock->expects($this->never()) - ->method('save'); + $this->eventSaverMock->expects($this->never())->method('save'); $this->observer->execute($this->eventObserverMock); } } From bcc19dc4002ffe158cb2c77b38852c676f53f86e Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 31 Jan 2020 16:43:29 +0200 Subject: [PATCH 396/666] Code cleaning --- .../Block/Tracking/PopupDeliveryDateTest.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php index 109f6199b52c6..f9865793129d3 100644 --- a/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Plugin/Block/Tracking/PopupDeliveryDateTest.php @@ -17,7 +17,7 @@ use PHPUnit\Framework\TestCase; /** - * Unit Test for @see \Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate + * Unit Test for \Magento\Fedex\Plugin\Block\Tracking\PopupDeliveryDate */ class PopupDeliveryDateTest extends TestCase { @@ -63,9 +63,7 @@ public function testAfterFormatDeliveryDateTimeWithFedexCarrier() $this->trackingStatusMock->expects($this::once()) ->method('getCarrier') ->willReturn(Carrier::CODE); - - $this->subjectMock->expects($this->once()) - ->method('formatDeliveryDate'); + $this->subjectMock->expects($this->once())->method('formatDeliveryDate'); $this->executeOriginalMethod(); } @@ -78,15 +76,13 @@ public function testAfterFormatDeliveryDateTimeWithOtherCarrier() $this->trackingStatusMock->expects($this::once()) ->method('getCarrier') ->willReturn(self::STUB_CARRIER_CODE_NOT_FEDEX); - - $this->subjectMock->expects($this->never()) - ->method('formatDeliveryDate'); + $this->subjectMock->expects($this->never())->method('formatDeliveryDate'); $this->executeOriginalMethod(); } /** - * Returns Mock for @see Status + * Returns Mock for \Magento\Shipping\Model\Tracking\Result\Status * * @return MockObject */ @@ -99,7 +95,7 @@ private function getStatusMock(): MockObject } /** - * Returns Mock for @see Popup + * Returns Mock for \Magento\Shipping\Block\Tracking\Popup * * @return MockObject */ From 1c6a7a3518343991909fa9605d173f9de1f1fb42 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 23:11:23 +0100 Subject: [PATCH 397/666] #CoreReview Fix backward compatibility --- .../Block/Product/ProductsList.php | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php index 4a75c806aa37b..2175889ce84e8 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php +++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php @@ -8,6 +8,7 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Block\Product\AbstractProduct; +use Magento\Catalog\Block\Product\Context; use Magento\Catalog\Block\Product\Widget\Html\Pager; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Visibility; @@ -16,7 +17,7 @@ use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\CatalogWidget\Model\Rule; use Magento\Framework\App\ActionInterface; -use Magento\Framework\App\Http\Context; +use Magento\Framework\App\Http\Context as HttpContext; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Exception\LocalizedException; @@ -27,7 +28,7 @@ use Magento\Framework\View\LayoutFactory; use Magento\Framework\View\LayoutInterface; use Magento\Rule\Model\Condition\Combine; -use Magento\Rule\Model\Condition\Sql\Builder; +use Magento\Rule\Model\Condition\Sql\Builder as SqlBuilder; use Magento\Widget\Block\BlockInterface; use Magento\Widget\Helper\Conditions; @@ -69,7 +70,7 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn protected $pager; /** - * @var Context + * @var HttpContext */ protected $httpContext; @@ -88,7 +89,7 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn protected $productCollectionFactory; /** - * @var Builder + * @var SqlBuilder */ protected $sqlBuilder; @@ -135,34 +136,34 @@ class ProductsList extends AbstractProduct implements BlockInterface, IdentityIn private $categoryRepository; /** - * @param \Magento\Catalog\Block\Product\Context $context + * @param Context $context * @param CollectionFactory $productCollectionFactory * @param Visibility $catalogProductVisibility - * @param Context $httpContext - * @param Builder $sqlBuilder + * @param HttpContext $httpContext + * @param SqlBuilder $sqlBuilder * @param Rule $rule * @param Conditions $conditionsHelper - * @param CategoryRepositoryInterface $categoryRepository * @param array $data * @param Json|null $json * @param LayoutFactory|null $layoutFactory * @param EncoderInterface|null $urlEncoder + * @param CategoryRepositoryInterface|null $categoryRepository * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Catalog\Block\Product\Context $context, + Context $context, CollectionFactory $productCollectionFactory, Visibility $catalogProductVisibility, - Context $httpContext, - Builder $sqlBuilder, + HttpContext $httpContext, + SqlBuilder $sqlBuilder, Rule $rule, Conditions $conditionsHelper, - CategoryRepositoryInterface $categoryRepository, array $data = [], Json $json = null, LayoutFactory $layoutFactory = null, - EncoderInterface $urlEncoder = null + EncoderInterface $urlEncoder = null, + CategoryRepositoryInterface $categoryRepository = null ) { $this->productCollectionFactory = $productCollectionFactory; $this->catalogProductVisibility = $catalogProductVisibility; @@ -173,7 +174,8 @@ public function __construct( $this->json = $json ?: ObjectManager::getInstance()->get(Json::class); $this->layoutFactory = $layoutFactory ?: ObjectManager::getInstance()->get(LayoutFactory::class); $this->urlEncoder = $urlEncoder ?: ObjectManager::getInstance()->get(EncoderInterface::class); - $this->categoryRepository = $categoryRepository; + $this->categoryRepository = $categoryRepository ?? ObjectManager::getInstance() + ->get(CategoryRepositoryInterface::class); parent::__construct( $context, $data From 5000cd9aa766448ad3a9812052474f75beb96604 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Fri, 31 Jan 2020 23:19:46 +0100 Subject: [PATCH 398/666] #CoreReview Improve test readability with const STUB and extracting assertions, using Phrase placeholder --- .../DeleteCategoryWithEnabledFlatTest.php | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php index 357b7247412d9..efa19b98d077f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Delete/DeleteCategoryWithEnabledFlatTest.php @@ -24,6 +24,8 @@ */ class DeleteCategoryWithEnabledFlatTest extends AbstractBackendController { + const STUB_CATEGORY_ID = 333; + /** * @var IndexerRegistry */ @@ -79,13 +81,16 @@ protected function tearDown() */ public function testDeleteCategory(): void { - $this->assertEquals(1, $this->getFlatCategoryCollectionSizeByCategoryId(333)); - $this->getRequest()->setMethod(HttpRequest::METHOD_POST); - $this->getRequest()->setPostValue(['id' => 333]); - $this->dispatch('backend/catalog/category/delete'); + // Given + $this->assertEquals(1, $this->getFlatCategoryCollectionSizeByCategoryId(self::STUB_CATEGORY_ID)); + + // When + $this->sendDeleteCategoryRequest(self::STUB_CATEGORY_ID); + + // Then $this->assertSessionMessages($this->equalTo([(string)__('You deleted the category.')])); - $this->assertEquals(0, $this->getFlatCategoryCollectionSizeByCategoryId(333)); - $this->checkCategoryIsDeleted(333); + $this->assertEquals(0, $this->getFlatCategoryCollectionSizeByCategoryId(self::STUB_CATEGORY_ID)); + $this->checkCategoryIsDeleted(self::STUB_CATEGORY_ID); } /** @@ -106,10 +111,26 @@ private function getFlatCategoryCollectionSizeByCategoryId(int $categoryId): int * Assert that category is deleted. * * @param int $categoryId + * @return void */ private function checkCategoryIsDeleted(int $categoryId): void { - $this->expectExceptionObject(new NoSuchEntityException(__("No such entity with id = {$categoryId}"))); + $this->expectExceptionObject( + new NoSuchEntityException(__("No such entity with id = %entityId", ['entityId' => $categoryId])) + ); $this->categoryRepository->get($categoryId); } + + /** + * Method passes the request to Backend to remove given category. + * + * @param int $categoryId + * @return void + */ + private function sendDeleteCategoryRequest(int $categoryId): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue(['id' => $categoryId]); + $this->dispatch('backend/catalog/category/delete'); + } } From 075f9f4d16a723095e1a0e77599e5e56fb78796d Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 02:07:14 +0100 Subject: [PATCH 399/666] Trigger cron execution on `index` group to show products --- .../AdminEditRelatedBundleProductTest.xml | 2 + .../Test/StorefrontEditBundleProductTest.xml | 2 + ...ConfigurableSetEditRelatedProductsTest.xml | 1 + .../Mftf/Test/StorefrontTaxQuoteCartTest.xml | 4 ++ .../Test/StorefrontTaxQuoteCheckoutTest.xml | 40 +++++++++++-------- ...eProductFromShoppingCartToWishlistTest.xml | 3 +- 6 files changed, 34 insertions(+), 18 deletions(-) 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 @@ <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedSee"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct1.sku$$" stepKey="seeRelatedProduct"/> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <!--See related product in storefront--> <amOnPage url="{{BundleProduct.sku}}.html" stepKey="goToStorefront"/> <waitForPageLoad stepKey="waitForStorefront"/> 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 @@ <click stepKey="saveProductBundle" selector="{{AdminProductFormActionSection.saveButton}}"/> <see stepKey="assertSuccess" selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product."/> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <!-- Go to the storefront bundled product page --> <amOnPage url="/{{BundleProduct.urlKey}}.html" stepKey="visitStoreFrontBundle"/> <waitForPageLoad stepKey="waitForStorefront"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml index bba8232139d69..a0f8da074536f 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml @@ -21,6 +21,7 @@ </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/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml index f0fac38a6c05c..6cda9ea88119b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml @@ -275,6 +275,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 +387,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/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml index 3a823efbcdf61..446c06ee1070c 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml @@ -52,8 +52,7 @@ <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 --> From e943bda91d0b03a0fc67fb78b82254986796396c Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Sat, 1 Feb 2020 12:25:23 +1030 Subject: [PATCH 400/666] #26622 - Check quote item for parentItem instead of parentItemId, as the latter is only set in beforeSave function. --- app/code/Magento/SalesRule/Model/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index dad35165051ce..addfd6107f600 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,7 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItemId()) { + if ($item->getParentItem()) { continue; } if (!$rule->getActions()->validate($item)) { From dab9463a523d51648b36bab7bbc26364bf23f944 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 11:23:17 +0100 Subject: [PATCH 401/666] Trigger cron execution on `index` group to show products --- .../Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml | 2 ++ .../Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml | 1 + .../Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml | 1 + .../Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml | 2 ++ .../Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml | 2 ++ .../Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml | 1 + 6 files changed, 9 insertions(+) diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml index dc8cb24246567..5ccd4d97555bb 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 @@ <actionGroup ref="LoginAsAdmin" stepKey="login"/> <createData entity="SimpleProduct2" stepKey="simpleProduct1"/> <createData entity="SimpleProduct2" stepKey="simpleProduct2"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> <!-- Delete the bundled 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..f919bd15ac9eb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml @@ -27,6 +27,7 @@ <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/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml index ae7b8d2446380..14fce9d4edf7c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml @@ -21,6 +21,7 @@ <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/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/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/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml index 6cda9ea88119b..e7bf7702328c0 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml @@ -41,6 +41,7 @@ </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"> From fe153fbd5eccef22c562016c4cac1ba4194e8abd Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 11:38:51 +0100 Subject: [PATCH 402/666] Wait for Customer Section load --- .../Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index 4260417b46fd0..e51a301212055 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}}"/> From 324ee916643f3b936d4f65eb82b35ed3085debb9 Mon Sep 17 00:00:00 2001 From: Michele Fantetti <mfantetti@ittweb.net> Date: Sat, 1 Feb 2020 11:41:13 +0100 Subject: [PATCH 403/666] Add frontend template hints status command unit tests after suggestions --- .../Command/TemplateHintsStatusCommand.php | 10 ++++++- .../TemplateHintsStatusCommandTest.php | 26 +++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index d6569622d17ce..c4d4d0109b1b5 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -66,7 +66,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->reinitableConfig->reinit(); $templateHintsStatus = - $this->scopeConfig->isSetFlag(self::TEMPLATE_HINTS_STOREFRONT_PATH, 'default') + ($this->isTemplateHintsEnabled()) ? 'enabled' : 'disabled'; $templateHintsMessage = __("Template hints are %status", ['status' => $templateHintsStatus]); @@ -74,4 +74,12 @@ public function execute(InputInterface $input, OutputInterface $output) return Cli::RETURN_SUCCESS; } + + /** + * @return bool + */ + private function isTemplateHintsEnabled(): bool + { + return $this->scopeConfig->isSetFlag(self::TEMPLATE_HINTS_STOREFRONT_PATH, 'default'); + } } diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php index 1c7ecaf161003..1aec1d71b434d 100644 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/TemplateHintsStatusCommandTest.php @@ -49,16 +49,26 @@ protected function setUp() } /** - * Verify execution + * Verify ScopeConfigInterface instance */ - public function testExecute() + public function testScopeConfigInterfaceInstance() { - $tester = new CommandTester($this->command); - $tester->execute([]); + $this->assertInstanceOf(ScopeConfigInterface::class, $this->scopeConfigMock); + } - $this->assertEquals( - Cli::RETURN_SUCCESS, - $tester->getStatusCode() - ); + /** + * Verify ReinitableConfigInterface instance + */ + public function testReinitableConfigInterfaceInstance() + { + $this->assertInstanceOf(ReinitableConfigInterface::class, $this->reinitableConfigMock); + } + + /** + * Verify TemplateHintsStatusCommand instance + */ + public function testCommandInstance() + { + $this->assertInstanceOf(TemplateHintsStatusCommand::class, $this->command); } } From 7fafb2d13517705d86ca0c65cfa52d52bd1c5c40 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 1 Feb 2020 17:41:26 +0530 Subject: [PATCH 404/666] More method cover with jasmine tests --- .../Ui/base/js/grid/data-storage.test.js | 133 +++++++++++++++++- 1 file changed, 129 insertions(+), 4 deletions(-) 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 f595020673ed7..163466ebe9175 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,9 +6,11 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ define([ + 'jquery', 'mageUtils', + 'underscore', 'Magento_Ui/js/grid/data-storage' -], function (utils, DataStorage) { +], function ($, utils, _, DataStorage) { 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { @@ -322,7 +324,12 @@ define([ describe('"updateData" method', function () { var model = new DataStorage({ - dataScope: 'magento' + dataScope: 'magento', + requestConfig: { + url: 'magento.com', + method: 'GET', + dataType: 'json' + } }); it('Check for defined ', function () { @@ -345,6 +352,83 @@ define([ }); }); + describe('"requestData" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined', function () { + expect(model.hasOwnProperty('requestData')).toBeDefined(); + }); + + it('Check method type', function () { + var type = typeof model.requestData; + + expect(type).toEqual('function'); + }); + + it('Check Ajax request', function () { + var params = { + namespace: 'magento', + search: '', + filters: { + store_id: 0 + }, + sorting: {}, + paging: {} + }, + query = utils.copy(params); + + spyOn(model, 'onRequestComplete'); + spyOn($, 'ajax').and.callFake(function () { + return { + /** + * Success result for ajax request + */ + done: function () { + model.onRequestComplete(model, query); + } + }; + }); + model.requestData(params); + expect($.ajax).toHaveBeenCalled(); + expect(model.onRequestComplete).toHaveBeenCalled(); + }); + }); + + describe('"getRequest" method', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); + + it('Check for defined', function () { + expect(model.hasOwnProperty('getRequest')).toBeDefined(); + }); + + it('Check method', function () { + var type = typeof model.getRequest; + + expect(type).toEqual('function'); + }); + + it('check "getRequest" has been executed', function () { + var params = { + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }; + + model._requests.push({ + ids: ['1'], + params: params, + totalRecords: 1, + errorMessage: '' + }); + expect(model.getRequest(params)).toBeTruthy(); + }); + }); + describe('"getRequestData" method', function () { var model = new DataStorage({ dataScope: 'magento' @@ -367,6 +451,45 @@ define([ expect(model.getRequestData(request)).toBeTruthy(); }); + + it('check "getByIds" has been executed', function () { + var request = { + ids: [1,2,3] + }; + + spyOn(model, 'getByIds'); + model.getRequestData(request); + expect(model.getByIds).toHaveBeenCalled(); + }); + + it('check "delay" function has been executed', function () { + var request = { + ids: [1,2,3], + totalRecords: 3, + errorMessage: '' + }; + + spyOn(_, 'delay'); + model.getRequestData(request); + expect(_.delay).toHaveBeenCalled(); + }); + + it('check "delay" function has not been executed', function () { + var request = { + ids: [1,2,3], + totalRecords: 3, + errorMessage: '' + }; + + model = new DataStorage({ + dataScope: 'magento', + cachedRequestDelay: 0 + }); + + spyOn(_, 'delay'); + model.getRequestData(request); + expect(_.delay).not.toHaveBeenCalled(); + }); }); describe('"cacheRequest" method', function () { @@ -531,7 +654,9 @@ define([ paging: {} }; - model.wasRequested(params); + spyOn(model, 'getRequest').and.callFake(function () { + return false; + }); expect(model.wasRequested(params)).toBeFalsy(); }); }); @@ -558,7 +683,7 @@ define([ entity_id: '1' }] }, -params = { + params = { namespace: 'magento', search: '', sorting: {}, From c9d83d7f74c5e7472c261c7e4ec057af5989c372 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 15:36:36 +0100 Subject: [PATCH 405/666] Extend Credit Card expiration date for another 4 years --- .../app/Magento/Braintree/Test/Repository/CreditCard.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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> From 148011a08aa169f11c9228797ecca6d048ae2aea Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 16:27:08 +0100 Subject: [PATCH 406/666] Fix invalid XML syntax --- .../Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index e51a301212055..3cb37a248aa30 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -17,7 +17,7 @@ </arguments> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <waitForElementVisible selector="{{StorefrontPanelHeaderSection.createAnAccountLink}}" stepKey="waitForCreateAccountLink"> + <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}}"/> From 2bdbf8b2c15873f8c0ff60bf7cfb279ce6f4039c Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 17:51:33 +0100 Subject: [PATCH 407/666] Reindex after creating Bundle product --- .../Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml index 5ccd4d97555bb..3aa0784f3fa55 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml @@ -91,6 +91,9 @@ <!-- Save product and go to storefront --> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexerAfterBundle"/> + <amOnPage url="{{BundleProduct.sku}}.html" stepKey="goToStorefront"/> <waitForPageLoad stepKey="waitForStorefront"/> <click selector="{{StorefrontBundledSection.addToCart}}" stepKey="clickCustomize"/> From 8450dc970f11713342984102970ac75d7aac9fc1 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 18:41:09 +0100 Subject: [PATCH 408/666] Add <wait> before running cron, as simultaneously running workers are overlapping Cron executions --- .../AdminEditRelatedBundleProductTest.xml | 1 + ...rontCheckBundleProductOptionTierPrices.xml | 4 +- ...tCustomerSelectAndSetBundleOptionsTest.xml | 2 + .../Test/StorefrontEditBundleProductTest.xml | 1 + .../Catalog/Test/Mftf/Data/ProductData.xml | 140 +++++++++--------- .../AdminSimpleSetEditRelatedProductsTest.xml | 2 + ...ntOnePageCheckoutDataWhenChangeQtyTest.xml | 2 + ...ConfigurableSetEditRelatedProductsTest.xml | 2 + ...DownloadableSetEditRelatedProductsTest.xml | 1 + ...AdminGroupedSetEditRelatedProductsTest.xml | 1 + .../Mftf/Test/StorefrontTaxQuoteCartTest.xml | 2 + .../Test/StorefrontTaxQuoteCheckoutTest.xml | 2 + ...eProductFromShoppingCartToWishlistTest.xml | 2 + ...eProductFromShoppingCartToWishlistTest.xml | 5 +- 14 files changed, 93 insertions(+), 74 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml index fbb9dda50f0d9..8a7e3b8344f86 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml @@ -70,6 +70,7 @@ <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedSee"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct1.sku$$" stepKey="seeRelatedProduct"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml index 0487668c10094..8e482ea8f1551 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -44,8 +44,8 @@ </actionGroup> <actionGroup ref="logout" stepKey="logoutAsAdmin"/> - <!-- Run reindex --> - <magentoCLI command="indexer:reindex" stepKey="reindex"/> + <wait stepKey="waitBeforeIndexer" time="60"/> + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> <deleteData createDataKey="createBundleProductCreateBundleProduct" stepKey="deleteDynamicBundleProduct"/> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml index 3aa0784f3fa55..68b2eda76c569 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml @@ -23,6 +23,7 @@ <createData entity="SimpleProduct2" stepKey="simpleProduct1"/> <createData entity="SimpleProduct2" stepKey="simpleProduct2"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> @@ -92,6 +93,7 @@ <!-- Save product and go to storefront --> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <wait stepKey="waitBeforeIndexerAfterBundle" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexerAfterBundle"/> <amOnPage url="{{BundleProduct.sku}}.html" stepKey="goToStorefront"/> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml index 3a40a1b7eeb71..8a9a01809f015 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml @@ -65,6 +65,7 @@ <click stepKey="saveProductBundle" selector="{{AdminProductFormActionSection.saveButton}}"/> <see stepKey="assertSuccess" selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product."/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!-- Go to the storefront bundled product page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index b160d958f423b..653a326e1c98b 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,38 +100,38 @@ <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="sku" unique="suffix">simple-product</data> + <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> @@ -140,10 +140,10 @@ <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> @@ -153,59 +153,59 @@ <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> @@ -213,10 +213,10 @@ <requiredEntity type="product_extension_attribute">EavStockItem</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> @@ -227,10 +227,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> @@ -238,25 +238,25 @@ <requiredEntity type="custom_attribute">CustomAttributeProductAttribute</requiredEntity> </entity> <entity name="ApiSimpleOutOfStock" type="product2"> - <data key="sku" unique="suffix">api-simple-product</data> + <data key="name" unique="suffix">Api Simple Out Of Stock Product</data> + <data key="sku" unique="suffix">apisimpleproduct</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="sku" unique="suffix">api-simple-product</data> + <data key="name" unique="suffix">Api Simple Product</data> + <data key="sku" unique="suffix">apisimpleproduct</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> @@ -266,26 +266,26 @@ <data key="sku" unique="suffix">pr</data> </entity> <entity name="ApiSimpleOneHidden" type="product2"> - <data key="sku" unique="suffix">api-simple-product</data> + <data key="name" unique="suffix">Api Simple Product</data> + <data key="sku" unique="suffix">apisimpleproduct</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="sku" unique="suffix">api-simple-product-two</data> + <data key="name" unique="suffix">Api Simple Product Two</data> + <data key="sku" unique="suffix">apisimpleproducttwo</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> @@ -301,23 +301,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> @@ -325,10 +325,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> @@ -379,52 +379,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> @@ -432,13 +432,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> @@ -447,13 +447,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> @@ -461,13 +461,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> @@ -475,13 +475,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> @@ -489,26 +489,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> @@ -573,13 +573,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> @@ -587,13 +587,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> @@ -601,15 +601,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> @@ -636,7 +636,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> @@ -644,7 +644,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> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml index f919bd15ac9eb..74ba1badbce85 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"/> + + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml index 14fce9d4edf7c..a32b946752731 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"/> + + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml index a0f8da074536f..4be3b841c0bc7 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"/> + + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml index 27d505e070f5b..18c3a1d34378b 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml @@ -34,6 +34,7 @@ <argument name="product" value="DownloadableProduct"/> </actionGroup> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml index a0698224b780c..24e96f3695ad3 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml @@ -34,6 +34,7 @@ <argument name="product" value="GroupedProduct"/> </actionGroup> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml index e7bf7702328c0..a350fc0acd766 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml @@ -277,6 +277,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> @@ -389,6 +390,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml index 050ab3889984b..b0825b530f42b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml @@ -148,6 +148,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> @@ -270,6 +271,7 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml index 446c06ee1070c..bd480a202ac22 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml @@ -52,6 +52,8 @@ <scrollTo selector="{{AdminProductFormBundleSection.contentDropDown}}" stepKey="scrollToBundleSection"/> <selectOption userInput="Separately" selector="{{AdminProductFormBundleSection.shipmentType}}" stepKey="selectSeparately"/> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + + <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml index 2d83043f81318..faea1e736a1b7 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml @@ -43,8 +43,9 @@ <requiredEntity createDataKey="createBundleOption1_1"/> <requiredEntity createDataKey="simpleProduct2"/> </createData> - <magentoCLI stepKey="reindex" command="indexer:reindex"/> - <magentoCLI stepKey="flushCache" command="cache:flush"/> + + <wait stepKey="waitBeforeIndexer" time="60"/> + <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> <!-- Delete data --> From a2e16f34fc028da456ab29409d686a7fbf2289da Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 18:44:01 +0100 Subject: [PATCH 409/666] Extend Credit Card expiration date for another 4 years --- .../Magento/Payment/Test/Repository/CreditCard.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index 7e3266cadf0a3..8711f4a70346b 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -10,7 +10,7 @@ <dataset name="visa_default"> <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> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -18,28 +18,28 @@ <field name="cc_type" xsi:type="string">Visa</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> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="visa_alt"> <field name="cc_number" xsi:type="string">4012888888881881</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2021</field> + <field name="cc_exp_year" xsi:type="string">2024</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="amex_default"> <field name="cc_number" xsi:type="string">378282246310005</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2021</field> + <field name="cc_exp_year" xsi:type="string">2024</field> <field name="cc_cid" xsi:type="string">1234</field> </dataset> <dataset name="visa_direct"> <field name="cc_number" xsi:type="string">4617747819866651</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> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -54,14 +54,14 @@ <dataset name="visa_cvv_mismatch"> <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> <field name="cc_cid" xsi:type="string">306</field> </dataset> <dataset name="mastercard_default"> <field name="cc_number" xsi:type="string">5555555555554444</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> <field name="cc_cid" xsi:type="string">123</field> </dataset> </repository> From 9de1e591300d8b77a7aeeffda2c3c01ab4763e55 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 1 Feb 2020 23:27:22 +0530 Subject: [PATCH 410/666] Fixed static tests --- .../code/Magento/Ui/base/js/grid/data-storage.test.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 163466ebe9175..02d303782a9d5 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 @@ -480,12 +480,10 @@ define([ totalRecords: 3, errorMessage: '' }; - - model = new DataStorage({ - dataScope: 'magento', - cachedRequestDelay: 0 - }); - + model = new DataStorage({ + dataScope: 'magento', + cachedRequestDelay: 0 + }); spyOn(_, 'delay'); model.getRequestData(request); expect(_.delay).not.toHaveBeenCalled(); From e52bc2a701818967ea9a7bf79cc1b05513276178 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 20:33:27 +0100 Subject: [PATCH 411/666] Add indexing after creating products + changes due to invalid use of `sku` as URL Key :-( --- app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml | 8 ++++---- .../Mftf/Test/CartPriceRuleForConfigurableProductTest.xml | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 653a326e1c98b..a7aed3392d469 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -239,7 +239,7 @@ </entity> <entity name="ApiSimpleOutOfStock" type="product2"> <data key="name" unique="suffix">Api Simple Out Of Stock Product</data> - <data key="sku" 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> @@ -251,7 +251,7 @@ </entity> <entity name="ApiSimpleOne" type="product2"> <data key="name" unique="suffix">Api Simple Product</data> - <data key="sku" 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> @@ -267,7 +267,7 @@ </entity> <entity name="ApiSimpleOneHidden" type="product2"> <data key="name" unique="suffix">Api Simple Product</data> - <data key="sku" 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> @@ -280,7 +280,7 @@ </entity> <entity name="ApiSimpleTwo" type="product2"> <data key="name" unique="suffix">Api Simple Product Two</data> - <data key="sku" unique="suffix">apisimpleproducttwo</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> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index ec9246f7c33bd..baf109b4a12f1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -74,6 +74,10 @@ <requiredEntity createDataKey="createConfigProduct"/> <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> + + <wait stepKey="waitBeforeIndexer" time="60"/> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> @@ -118,13 +122,13 @@ <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> <!-- Add the first product to the cart --> - <amOnPage url="$$createConfigChildProduct1.sku$$.html" stepKey="goToProductPage1"/> + <amOnPage url="$$createConfigChildProduct1.urlKey$$.html" stepKey="goToProductPage1"/> <waitForPageLoad stepKey="waitForProductPageLoad1"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart1"/> <waitForPageLoad stepKey="waitForAddToCart1"/> <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> <!-- Add the second product to the cart --> - <amOnPage url="$$createConfigChildProduct2.sku$$.html" stepKey="goToProductPage2"/> + <amOnPage url="$$createConfigChildProduct2.urlKey$$.html" stepKey="goToProductPage2"/> <waitForPageLoad stepKey="waitForProductPageLoad2"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> <waitForPageLoad stepKey="waitForAddToCart2"/> From 548da895caa3393ce951ce0675fea398c5a1910b Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sat, 1 Feb 2020 20:46:45 +0100 Subject: [PATCH 412/666] urlKey is not used --- .../Mftf/Test/CartPriceRuleForConfigurableProductTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index baf109b4a12f1..d44e89aef8e25 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -122,13 +122,13 @@ <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> <!-- Add the first product to the cart --> - <amOnPage url="$$createConfigChildProduct1.urlKey$$.html" stepKey="goToProductPage1"/> + <amOnPage url="$$createConfigChildProduct1.sku$$.html" stepKey="goToProductPage1"/> <waitForPageLoad stepKey="waitForProductPageLoad1"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart1"/> <waitForPageLoad stepKey="waitForAddToCart1"/> <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> <!-- Add the second product to the cart --> - <amOnPage url="$$createConfigChildProduct2.urlKey$$.html" stepKey="goToProductPage2"/> + <amOnPage url="$$createConfigChildProduct2.sku$$.html" stepKey="goToProductPage2"/> <waitForPageLoad stepKey="waitForProductPageLoad2"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addProductToCart2"/> <waitForPageLoad stepKey="waitForAddToCart2"/> From df14b1c46675a4a59eb57f1b1b1e6fbec697a1b4 Mon Sep 17 00:00:00 2001 From: Vikalp Saxena <vikalpsaxena@cedcommerce.com> Date: Sun, 2 Feb 2020 10:49:24 +0530 Subject: [PATCH 413/666] Fixed #26513 Added missing Array param type in comment in \Magento\Quote\Model\Quote\Item::addOption #26513 --- app/code/Magento/Quote/Model/Quote/Item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/Model/Quote/Item.php b/app/code/Magento/Quote/Model/Quote/Item.php index d14ae008ce407..2e4a9c7ded683 100644 --- a/app/code/Magento/Quote/Model/Quote/Item.php +++ b/app/code/Magento/Quote/Model/Quote/Item.php @@ -609,7 +609,7 @@ public function getOptionsByCode() /** * Add option to item * - * @param \Magento\Quote\Model\Quote\Item\Option|\Magento\Framework\DataObject $option + * @param \Magento\Quote\Model\Quote\Item\Option|\Magento\Framework\DataObject|array $option * @return $this * @throws \Magento\Framework\Exception\LocalizedException */ From 71cc328d7792d089b62939a71486e770299240ad Mon Sep 17 00:00:00 2001 From: Pratik Sangani <pratiksangani95@gmail.com> Date: Sun, 2 Feb 2020 12:18:12 +0530 Subject: [PATCH 414/666] Xml fixes --- app/code/Magento/AdvancedPricingImportExport/etc/module.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 230fb17ae5544..4482ba7a0a5e8 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/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_AdvancedPricingImportExport" > - </module> + <module name="Magento_AdvancedPricingImportExport" /> </config> From f9f5e30a692725451bb0ada271cfaf3f594e22e5 Mon Sep 17 00:00:00 2001 From: Sanchit <sanchit@cueblocks.com> Date: Sun, 2 Feb 2020 12:21:51 +0530 Subject: [PATCH 415/666] ProductToolbarTypoFix: Grit Typo Fix --- app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php b/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php index c530ba4785ad9..48725331b27da 100644 --- a/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php +++ b/app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php @@ -263,7 +263,7 @@ public function getCurrentPage() } /** - * Get grit products sort order field + * Get grid products sort order field * * @return string */ From e088db1dcacf61f5861a8fffa607eabaef2ae66a Mon Sep 17 00:00:00 2001 From: Serhii Petrychenko <s.petrychenko@gmail.com> Date: Sun, 2 Feb 2020 10:54:12 +0200 Subject: [PATCH 416/666] issue-#25675 Added fix for #25675 issue to the 2.4 Magento version --- .../QuantityValidator/QuoteItemQtyList.php | 14 ++-- .../QuoteItemQtyListTest.php | 68 +++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php 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/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..5966b530f72e1 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php @@ -0,0 +1,68 @@ +<?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 + */ +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); + } +} From 1f96b873283229aa6892444244475d9992c0d8f2 Mon Sep 17 00:00:00 2001 From: Dasharath <dasharath@wagento.com> Date: Sun, 2 Feb 2020 15:00:42 +0530 Subject: [PATCH 417/666] [26054-Do not duplicate SEO meta data when duplicating a product] --- app/code/Magento/Catalog/Model/Product/Copier.php | 7 +++---- .../Magento/Catalog/Test/Unit/Model/Product/CopierTest.php | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index a7f7bad1a5167..22419123d1614 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -78,6 +78,9 @@ public function copy(Product $product) $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); @@ -89,10 +92,6 @@ public function copy(Product $product) $this->setDefaultUrl($product, $duplicate); $this->setStoresUrl($product, $duplicate); $this->getOptionRepository()->duplicate($product, $duplicate); - $product->getResource()->duplicate( - $product->getData($metadata->getLinkField()), - $duplicate->getData($metadata->getLinkField()) - ); return $duplicate; } 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 809fa0225278c..34fddc06f1c42 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -197,6 +197,9 @@ public function testCopy() $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); From ea4a31ee10de19ab2d1cddb164eac62504e2fd1c Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sun, 2 Feb 2020 11:12:42 +0100 Subject: [PATCH 418/666] Trying to avoid waitForIndex --- .../Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml | 1 - .../Test/StorefrontCheckBundleProductOptionTierPrices.xml | 1 - .../Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml | 1 - .../Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml | 1 - .../Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml | 1 - .../Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml | 1 - .../Test/Mftf/Data/ConfigurableProductData.xml | 4 ++-- .../Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml | 1 - .../Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml | 1 - .../Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml | 1 - .../Mftf/Test/CartPriceRuleForConfigurableProductTest.xml | 1 - .../Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml | 2 -- .../Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml | 2 -- ...MoveDynamicBundleProductFromShoppingCartToWishlistTest.xml | 1 - ...ntMoveFixedBundleProductFromShoppingCartToWishlistTest.xml | 1 - 15 files changed, 2 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml index 8a7e3b8344f86..fbb9dda50f0d9 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminEditRelatedBundleProductTest.xml @@ -70,7 +70,6 @@ <conditionalClick selector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDropdown}}" dependentSelector="{{AdminProductFormRelatedUpSellCrossSellSection.relatedDependent}}" visible="false" stepKey="openDropDownIfClosedRelatedSee"/> <see selector="{{AdminProductFormRelatedUpSellCrossSellSection.selectedRelatedProduct}}" userInput="$$simpleProduct1.sku$$" stepKey="seeRelatedProduct"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml index 8e482ea8f1551..6c6cc9185380b 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCheckBundleProductOptionTierPrices.xml @@ -44,7 +44,6 @@ </actionGroup> <actionGroup ref="logout" stepKey="logoutAsAdmin"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml index 68b2eda76c569..613187a4c3856 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontCustomerSelectAndSetBundleOptionsTest.xml @@ -23,7 +23,6 @@ <createData entity="SimpleProduct2" stepKey="simpleProduct1"/> <createData entity="SimpleProduct2" stepKey="simpleProduct2"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml index 8a9a01809f015..3a40a1b7eeb71 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontEditBundleProductTest.xml @@ -65,7 +65,6 @@ <click stepKey="saveProductBundle" selector="{{AdminProductFormActionSection.saveButton}}"/> <see stepKey="assertSuccess" selector="{{AdminProductMessagesSection.successMessage}}" userInput="You saved the product."/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!-- Go to the storefront bundled product page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml index 74ba1badbce85..84eb3a843aa1f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleSetEditRelatedProductsTest.xml @@ -28,7 +28,6 @@ <createData entity="SimpleProduct2" stepKey="simpleProduct5"/> <createData entity="SimpleProduct2" stepKey="simpleProduct6"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml index a32b946752731..e335caa2ddb64 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontOnePageCheckoutDataWhenChangeQtyTest.xml @@ -22,7 +22,6 @@ <!--Create a product--> <createData entity="SimpleProduct2" stepKey="createProduct"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> 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/Test/AdminConfigurableSetEditRelatedProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml index 4be3b841c0bc7..924707a16600f 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableSetEditRelatedProductsTest.xml @@ -22,7 +22,6 @@ <before> <createData entity="ApiCategory" stepKey="createCategory"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml index 18c3a1d34378b..27d505e070f5b 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminDownloadableSetEditRelatedProductsTest.xml @@ -34,7 +34,6 @@ <argument name="product" value="DownloadableProduct"/> </actionGroup> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml index 24e96f3695ad3..a0698224b780c 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Test/AdminGroupedSetEditRelatedProductsTest.xml @@ -34,7 +34,6 @@ <argument name="product" value="GroupedProduct"/> </actionGroup> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <!--See related product in storefront--> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index d44e89aef8e25..9dbcc72cf5575 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -75,7 +75,6 @@ <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml index a350fc0acd766..e7bf7702328c0 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCartTest.xml @@ -277,7 +277,6 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> @@ -390,7 +389,6 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml index b0825b530f42b..050ab3889984b 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxQuoteCheckoutTest.xml @@ -148,7 +148,6 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> @@ -271,7 +270,6 @@ <click stepKey="clickSave" selector="{{AdminStoresMainActionsSection.saveButton}}"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI command="cron:run --group=index" stepKey="runCronIndexer"/> </before> <after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml index bd480a202ac22..9fffa51e7d3c7 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveDynamicBundleProductFromShoppingCartToWishlistTest.xml @@ -53,7 +53,6 @@ <selectOption userInput="Separately" selector="{{AdminProductFormBundleSection.shipmentType}}" stepKey="selectSeparately"/> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml index faea1e736a1b7..f942a8f314a67 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontMoveFixedBundleProductFromShoppingCartToWishlistTest.xml @@ -44,7 +44,6 @@ <requiredEntity createDataKey="simpleProduct2"/> </createData> - <wait stepKey="waitBeforeIndexer" time="60"/> <magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/> </before> <after> From b130bd0670b2190903f358ca036005020407cefb Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sun, 2 Feb 2020 13:23:22 +0100 Subject: [PATCH 419/666] Fix invalid URL for order_shipment page --- .../Magento/Shipping/Test/Mftf/Page/AdminShipmentNewPage.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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> From fc6fd6274bbc522cde5fd577556ae98f04de3d98 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Sun, 2 Feb 2020 15:19:23 +0100 Subject: [PATCH 420/666] Extend the time wait for success notification --- .../ActionGroup/AdminCreateInvoiceAndCreditMemoActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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> From 4e2662f9f2d863d2c657bd4c3a4d8b7263a8933a Mon Sep 17 00:00:00 2001 From: "rostyslav.hymon" <rostyslav.hymon@transoftgroup.com> Date: Mon, 3 Feb 2020 10:01:44 +0200 Subject: [PATCH 421/666] MC-30864: Payflow link payment method allways returns message: Your paiment has been declined --- app/code/Magento/Paypal/Model/Payflowlink.php | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) 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')] ?? ''; } /** From fab00b6bcc6c2cd537f038a952ee1b12e6f3a975 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Mon, 3 Feb 2020 10:39:31 +0200 Subject: [PATCH 422/666] MC-29999: A site with optional telephone will sometimes require one --- .../Model/Address/Validator/General.php | 15 +++++ app/code/Magento/Eav/Model/Config.php | 28 +++++---- .../Model/CustomerAddressAttributeTest.php | 63 +++++++++++++++++++ 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/CustomerAddressAttributeTest.php 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/Eav/Model/Config.php b/app/code/Magento/Eav/Model/Config.php index 20126d5146c35..68dd68b59e8ee 100644 --- a/app/code/Magento/Eav/Model/Config.php +++ b/app/code/Magento/Eav/Model/Config.php @@ -245,8 +245,8 @@ private function loadAttributes($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 */ @@ -296,9 +296,9 @@ protected function _getEntityTypeReference($id) /** * 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/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); + } + } +} From 587f3ce03d4f9766d98d1cbe0207ba1f355e731f Mon Sep 17 00:00:00 2001 From: Pratik Mehta <pratik@seepossible.com> Date: Mon, 3 Feb 2020 14:20:34 +0530 Subject: [PATCH 423/666] Comment add in translate. --- app/code/Magento/Backend/etc/adminhtml/system.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Backend/etc/adminhtml/system.xml b/app/code/Magento/Backend/etc/adminhtml/system.xml index 65744e56d94ac..91feb4b5167ad 100644 --- a/app/code/Magento/Backend/etc/adminhtml/system.xml +++ b/app/code/Magento/Backend/etc/adminhtml/system.xml @@ -115,7 +115,7 @@ <label>Enable Template Path Hints for Storefront</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> - <field id="template_hints_storefront_show_with_parameter" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> + <field id="template_hints_storefront_show_with_parameter" translate="label comment" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enable Hints for Storefront with URL Parameter</label> <depends> <field id="*/*/template_hints_storefront">1</field> @@ -123,7 +123,7 @@ <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Use URL parameter to enable template path hints for Storefront</comment> </field> - <field id="template_hints_parameter_value" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> + <field id="template_hints_parameter_value" translate="label comment" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"> <label>Parameter Value</label> <depends> <field id="*/*/template_hints_storefront">1</field> From 49cfa49da66cc6baf446b8e34b516377a1f85348 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 10:54:02 +0200 Subject: [PATCH 424/666] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- .../Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml | 2 +- ...SortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml index be0fdb2e0b419..8be6b809aa77b 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Section/AdminNewCatalogPriceRuleSection.xml @@ -63,7 +63,7 @@ <element name="targetEllipsisSelect" type="select" selector="select#conditions__{{var1}}--{{var2}}__value" parameterized="true" timeout="30"/> <element name="targetSelect" type="select" selector="//ul[@id='conditions__{{var}}__children']//select" parameterized="true" timeout="30"/> <element name="targetInput" type="input" selector="input#conditions__{{var1}}--{{var2}}__value" parameterized="true"/> - <element name="applyButton" type="button" selector="#conditions__{{var1}}__children li:nth-of-type({{var2}}) a.rule-param-apply" parameterized="true"/> + <element name="applyButton" type="button" selector="#conditions__{{var1}}__children li:nth-of-type({{var2}}) a.rule-param-apply" parameterized="true" timeout="30"/> <element name="condition" type="text" selector="//span[@class='rule-param']/a[text()='{{condition}}']" parameterized="true"/> <element name="activeOperatorSelect" type="select" selector=".rule-param-edit select[name*='[operator]']"/> <element name="activeValueInput" type="input" selector=".rule-param-edit [name*='[value]']"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 85f35703592c1..4e8274203365c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -152,7 +152,8 @@ <argument name="discountAmount" value="{{CatalogRuleByPercentWith96Amount.discount_amount}}"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <actionGroup ref="AdminReindexAndFlushCache" stepKey="reindexAndFlushCache"/> + <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product catalog_product_price catalogrule_rule" stepKey="reindexIndices"/> + <magentoCLI command="cache:clean" arguments="full_page block_html" stepKey="flushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> From f530fabca9d22552e8b9a938fc1978ca71fae590 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Mon, 3 Feb 2020 11:01:46 +0200 Subject: [PATCH 425/666] Fix namespace --- .../Tab/Front/ProductAttributeFormBuildFrontTabObserverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index ec9d113665850..42092a40a7679 100644 --- 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 @@ -6,7 +6,7 @@ declare(strict_types=1); -namespace Magento\LayeredNavigation\Test\Unit\Observer\Edit\Tab\Front\ProductAttributeFormBuildFrontTabObserverTest; +namespace Magento\LayeredNavigation\Test\Unit\Observer\Edit\Tab\Front; use Magento\Config\Model\Config\Source\Yesno; use Magento\Framework\Data\Form; From 0e7063ab0a6ed3458f04a1c31588e130a7699dba Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 11:07:26 +0200 Subject: [PATCH 426/666] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- ...tSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 4e8274203365c..15df342ca47a8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -153,7 +153,7 @@ </actionGroup> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> <magentoCLI command="indexer:reindex" arguments="catalogsearch_fulltext catalog_category_product catalog_product_price catalogrule_rule" stepKey="reindexIndices"/> - <magentoCLI command="cache:clean" arguments="full_page block_html" stepKey="flushCache"/> + <magentoCLI command="cache:clean" arguments="full_page" stepKey="flushCache"/> <!--Reopen category with products and Sort by price desc--> <actionGroup ref="GoToStorefrontCategoryPageByParametersActionGroup" stepKey="goToStorefrontCategoryPage2"> From 4ace1e6658a80a9b017cd5803b30fb3ed6189dd0 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 3 Feb 2020 11:39:21 +0200 Subject: [PATCH 427/666] cover changes with jasmine test --- .../frontend/web/js/swatch-renderer.test.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.test.js index f486123ba0bd3..144bfa4a77bce 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.test.js @@ -98,5 +98,37 @@ define([ widget._UpdatePrice(); expect(productPriceMock.find().find.calls.count()).toBe(1); }); + + it('check getSelectedOptionPriceIndex', function () { + var optionMock = '<div class="swatch-attribute" attribute-id="2" option-selected="4"></div>', + element = $('<div class="' + widget.options.tooltipClass + + '"><div class="image"></div><div class="title"></div><div class="corner"></div>' + + optionMock + '</div>' + ), + optionPricesMock = { + optionPrices: { + p: { + finalPrice: { + amount: 12 + } + } + } + }; + + widget.element = element; + widget.options.classes.attributeClass = 'swatch-attribute'; + widget.options.jsonConfig = optionPricesMock; + widget.optionsMap = { + 2: { + 4: { + products: 'p' + }, + hasOwnProperty: jasmine.createSpy().and.returnValue(true) + }, + hasOwnProperty: jasmine.createSpy().and.returnValue(true) + }; + + expect(widget._getSelectedOptionPriceIndex()).toBe('p'); + }); }); }); From c85ff66064bd8aaf9673ffaa7057ee86b32c67b6 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 12:14:44 +0200 Subject: [PATCH 428/666] MC-30164: [FT] [MFTF] [2.4] Fix flaky test AssignProductsToCategoryBySKUsTest (MC-172) --- ...enProductsInCategorySectionActionGroup.xml | 20 ++++++++++++++ .../AdminSaveCategoryFormActionGroup.xml | 21 +++++++++++++++ ...tCategorySimpleProductShownActionGroup.xml | 26 +++++++++++++++++++ .../SaveCategoryFormActionGroup.xml | 6 ++--- .../Section/AdminCategoryProductsSection.xml | 7 +++-- 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCategoryPageOpenProductsInCategorySectionActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSaveCategoryFormActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontCategorySimpleProductShownActionGroup.xml 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/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/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/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/Section/AdminCategoryProductsSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml index 8a993a74a58d1..1627fb9512e64 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml @@ -9,8 +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="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> \ No newline at end of file +</sections> From 9c0a76fe87c984043ffb7b189c37ed469058bc27 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Mon, 3 Feb 2020 12:20:55 +0200 Subject: [PATCH 429/666] Minor change --- .../Developer/Console/Command/TemplateHintsStatusCommand.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php index c4d4d0109b1b5..bc44df911213b 100644 --- a/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php +++ b/app/code/Magento/Developer/Console/Command/TemplateHintsStatusCommand.php @@ -76,6 +76,8 @@ public function execute(InputInterface $input, OutputInterface $output) } /** + * Check if template hints enabled + * * @return bool */ private function isTemplateHintsEnabled(): bool From da4d7b43f3f18407cfab5134070cc2b302ce6f89 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 12:34:19 +0200 Subject: [PATCH 430/666] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- ...ssignProductAttributeToAttributeSetTest.xml | 3 +++ .../Test/AdminChangeProductAttributeSet.xml | 3 +++ ...roductPriceWithDisabledChildProductTest.xml | 3 +++ ...stomAttributeValuesAfterProductSaveTest.xml | 3 +++ .../Test/AdminCreateAttributeSetEntityTest.xml | 3 +++ ...sibleInStorefrontAdvancedSearchFormTest.xml | 3 +++ ...sibleInStorefrontAdvancedSearchFormTest.xml | 3 +++ .../AdminCreateNewGroupForAttributeSetTest.xml | 3 +++ ...dminDeleteConfigurableChildProductsTest.xml | 3 +++ ...ownProductAttributeFromAttributeSetTest.xml | 3 +++ .../Test/AdminDeleteProductAttributeTest.xml | 3 +++ ...eldProductAttributeFromAttributeSetTest.xml | 3 +++ ...AdminNavigateMultipleUpSellProductsTest.xml | 3 +++ ...oductGridFilteringByCustomAttributeTest.xml | 3 +++ ...leForProductOptionsWithoutTierPriceTest.xml | 3 +++ ...ignProductAttributeFromAttributeSetTest.xml | 3 +++ ...eUsedInConfigurableProductAttributeTest.xml | 3 +++ ...nchorIsVisibleOnViewportOnceClickedTest.xml | 3 +++ ...StorefrontProductWithEmptyAttributeTest.xml | 3 +++ ...ntProductsCompareWithEmptyAttributeTest.xml | 3 +++ .../Mftf/Test/AdminExportBundleProductTest.xml | 3 +++ ...ImportConfigurableProductWithImagesTest.xml | 3 +++ ...nfigurableProductsWithCustomOptionsTest.xml | 3 +++ ...figurableProductsWithAssignedImagesTest.xml | 3 +++ ...rableProductAssignedToCustomWebsiteTest.xml | 3 +++ ...atedProductToConfigurableOutOfStockTest.xml | 17 ++++++++++------- ...onfigurableProductWithSpecialPricesTest.xml | 3 +++ .../AdminDeleteCatalogPriceRuleEntityTest.xml | 3 +++ ...yCatalogPriceRuleByProductAttributeTest.xml | 3 +++ ...RuleForSimpleAndConfigurableProductTest.xml | 3 +++ ...eProductWithAssignedSimpleProducts2Test.xml | 3 +++ ...leProductWithAssignedSimpleProductsTest.xml | 3 +++ ...eForConfigurableProductWithOptions2Test.xml | 3 +++ ...leForConfigurableProductWithOptionsTest.xml | 3 +++ .../Test/Mftf/Test/SearchEntityResultsTest.xml | 7 +++++++ ...ConfigurableProductFromShoppingCartTest.xml | 3 +++ .../OnePageCheckoutWithAllProductTypesTest.xml | 3 +++ ...ddConfigurableProductToShoppingCartTest.xml | 3 +++ ...ontCheckoutWithSpecialPriceProductsTest.xml | 3 +++ ...igurableProductFromMiniShoppingCartTest.xml | 3 +++ ...stCheckoutUsingFreeShippingAndTaxesTest.xml | 3 +++ .../AdminAddDefaultImageConfigurableTest.xml | 3 +++ ...ableProductAttributeValueUniquenessTest.xml | 3 +++ ...nCheckResultsOfColorAndOtherFiltersTest.xml | 3 +++ ...inCheckValidatorConfigurableProductTest.xml | 3 +++ .../AdminConfigurableProductDeleteTest.xml | 6 ++++++ .../AdminConfigurableProductLongSkuTest.xml | 3 +++ .../AdminConfigurableProductOutOfStockTest.xml | 9 +++++++++ .../AdminConfigurableProductSearchTest.xml | 6 ++++++ ...nConfigurableProductUpdateAttributeTest.xml | 6 ++++++ .../AdminConfigurableProductUpdateTest.xml | 6 ++++++ ...ProductWithDisabledChildrenProductsTest.xml | 3 +++ ...CreateConfigurableProductWithImagesTest.xml | 3 +++ ...reeProductDisplayOutOfStockProductsTest.xml | 3 +++ ...roductDontDisplayOutOfStockProductsTest.xml | 3 +++ ...rableProductWithTierPriceForOneItemTest.xml | 3 +++ .../AdminProductTypeSwitchingOnEditingTest.xml | 6 ++++++ .../Mftf/Test/AdminRelatedProductsTest.xml | 3 +++ ...AdminRemoveDefaultImageConfigurableTest.xml | 2 ++ .../AdvanceCatalogSearchConfigurableTest.xml | 16 ++++++++++++++++ ...ableProductPriceAdditionalStoreViewTest.xml | 2 ++ .../Mftf/Test/EndToEndB2CGuestUserTest.xml | 6 ++++++ .../Mftf/Test/EndToEndB2CLoggedInUserTest.xml | 3 +++ ...oductsListWidgetConfigurableProductTest.xml | 5 ++++- ...AvailableToConfigureDisabledProductTest.xml | 3 +++ ...ogSearchConfigurableBySkuWithHyphenTest.xml | 4 ++++ ...gurableProductCategoryViewChildOnlyTest.xml | 3 +++ ...frontConfigurableProductChildSearchTest.xml | 3 +++ ...torefrontConfigurableProductDetailsTest.xml | 3 +++ ...rConfigurableWithCatalogRuleAppliedTest.xml | 3 +++ ...onfigurableProductLayeredNavigationTest.xml | 3 +++ .../StorefrontClearAllCompareProductsTest.xml | 6 +++++- ...butesChangedValueToEmptyAfterImportTest.xml | 3 +++ .../CliRunReindexUsingCronJobsActionGroup.xml | 18 ++++++++++++++++++ ...thMapAssignedConfigProductIsCorrectTest.xml | 3 +++ ...refrontGuestCheckoutDisabledProductTest.xml | 3 +++ ...rableProductToOrderFromShoppingCartTest.xml | 3 +++ ...derWithCheckMoneyOrderPaymentMethodTest.xml | 3 +++ ...CreateCreditMemoConfigurableProductTest.xml | 3 +++ ...AdminSubmitConfigurableProductOrderTest.xml | 3 +++ .../CreateOrderFromEditCustomerPageTest.xml | 3 +++ ...urableProductsInComparedOnOrderPageTest.xml | 3 +++ ...deredConfigurableProductOnOrderPageTest.xml | 3 +++ ...iewedConfigurableProductOnOrderPageTest.xml | 3 +++ .../Test/StorefrontPrintOrderGuestTest.xml | 3 +++ ...CartPriceRuleForConfigurableProductTest.xml | 5 ++++- .../Mftf/Test/AdminCreateImageSwatchTest.xml | 3 +++ ...leteConfigurableProductFromWishlistTest.xml | 3 +++ 88 files changed, 330 insertions(+), 10 deletions(-) create mode 100644 app/code/Magento/Indexer/Test/Mftf/ActionGroup/CliRunReindexUsingCronJobsActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml index 41b358bbf760e..bcb8af7209d8f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAssignProductAttributeToAttributeSetTest.xml @@ -33,6 +33,9 @@ <after> <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" 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/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..6a3ff738f1846 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckConfigurableProductPriceWithDisabledChildProductTest.xml @@ -118,6 +118,9 @@ <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" 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..4aa9474aba6fe 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml @@ -43,6 +43,9 @@ <deleteData createDataKey="createMultiSelectProductAttribute" stepKey="deleteMultiSelectProductAttribute"/> <!-- Logout from Admin page --> <actionGroup ref="logout" 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/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/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 557f0768c98a3..166af767be142 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -35,6 +35,9 @@ </before> <after> <actionGroup ref="logout" 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/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 6bfd012bc88b2..56a6a869d8d35 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateMultipleSelectProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -41,6 +41,9 @@ <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" 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/AdminCreateNewGroupForAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml index a105f343d3e21..41662e4748193 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml @@ -28,6 +28,9 @@ <after> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <actionGroup ref="logout" 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/AdminDeleteConfigurableChildProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml index 4a305b8dfec75..04a4eff0a26d4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteConfigurableChildProductsTest.xml @@ -82,6 +82,9 @@ <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" 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..58e60da3bdac5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteDropdownProductAttributeFromAttributeSetTest.xml @@ -29,6 +29,9 @@ <!--Delete Created Data --> <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" 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..d72806cb0991d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteProductAttributeTest.xml @@ -23,6 +23,9 @@ </before> <after> <actionGroup ref="logout" 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/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index 4f05c364fda0e..e12bac55d8bc8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -32,6 +32,9 @@ <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> <actionGroup ref="logout" 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/AdminNavigateMultipleUpSellProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml index 5dd8b2e430941..7bfe3ae50c58b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminNavigateMultipleUpSellProductsTest.xml @@ -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/AdminProductGridFilteringByCustomAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml index 6f65865924bad..a4986117380ff 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminProductGridFilteringByCustomAttributeTest.xml @@ -90,6 +90,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="NavigateToAndResetProductGridToDefaultViewAfterTest"/> <actionGroup ref="logout" 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/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml index 4bcb82372e801..7f62dd14a4f32 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminTierPriceNotAvailableForProductOptionsWithoutTierPriceTest.xml @@ -83,6 +83,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <actionGroup ref="logout" 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..c508e3ae94d67 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUnassignProductAttributeFromAttributeSetTest.xml @@ -37,6 +37,9 @@ <deleteData createDataKey="attribute" stepKey="deleteAttribute"/> <magentoCLI command="cron:run --group=index" stepKey="runCron"/> <actionGroup ref="logout" 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/DeleteUsedInConfigurableProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml index 0daf8361ef9d1..0d382798a6266 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/DeleteUsedInConfigurableProductAttributeTest.xml @@ -73,6 +73,9 @@ <!-- Logout --> <actionGroup ref="logout" 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/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/StorefrontProductWithEmptyAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml index db693b7229b17..7ba8f26ba1c05 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductWithEmptyAttributeTest.xml @@ -29,6 +29,9 @@ <deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" 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..3aa12a7268593 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductsCompareWithEmptyAttributeTest.xml @@ -33,6 +33,9 @@ <deleteData createDataKey="createSimpleProduct1" stepKey="deleteSimpleProduct1"/> <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> <actionGroup ref="logout" 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/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml index 369805a94dd84..7fb4d8b025b07 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportBundleProductTest.xml @@ -107,6 +107,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" 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/AdminExportImportConfigurableProductWithImagesTest.xml b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml index 642bbfc0453c5..c27a1716e84e5 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportImportConfigurableProductWithImagesTest.xml @@ -153,6 +153,9 @@ <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridColumnsInitial"/> <!-- Admin logout--> <actionGroup ref="logout" 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..a55e92d64ce00 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleAndConfigurableProductsWithCustomOptionsTest.xml @@ -95,6 +95,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" 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..7131fe41ea5ec 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAndConfigurableProductsWithAssignedImagesTest.xml @@ -111,6 +111,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" 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..ea27d61e3b00c 100644 --- a/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml +++ b/app/code/Magento/CatalogImportExport/Test/Mftf/Test/AdminExportSimpleProductAssignedToMainWebsiteAndConfigurableProductAssignedToCustomWebsiteTest.xml @@ -96,6 +96,9 @@ </actionGroup> <!-- Log out --> <actionGroup ref="logout" 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/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Test/AssociatedProductToConfigurableOutOfStockTest.xml index 8458fcf3b94e0..07354d0b4c89f 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"> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml index d99ebac94fbec..453c64a32ce32 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml @@ -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/AdminDeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 02d998870fb65..d5efaec971bba 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -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/ApplyCatalogPriceRuleByProductAttributeTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml index 1615985370182..c3cb4d6180f18 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogPriceRuleByProductAttributeTest.xml @@ -105,6 +105,9 @@ <click stepKey="resetFilters" selector="{{AdminSecondaryGridSection.resetFilters}}"/> <actionGroup ref="logout" 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 1950f060790d7..9477f5cbed87e 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -99,6 +99,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/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml index 8b72b7616b6ff..80ff2a447052c 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProducts2Test.xml @@ -172,6 +172,9 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> <!-- Admin log out --> <actionGroup ref="logout" 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..ea0d8e01d540f 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithAssignedSimpleProductsTest.xml @@ -176,6 +176,9 @@ <!-- Admin log out --> <actionGroup ref="logout" 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..2a5786b38107f 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptions2Test.xml @@ -106,6 +106,9 @@ <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> <actionGroup ref="logout" 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..c077719dfa80b 100644 --- a/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml +++ b/app/code/Magento/CatalogRuleConfigurable/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithOptionsTest.xml @@ -123,6 +123,9 @@ <!-- Log out --> <actionGroup ref="logout" 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/Test/Mftf/Test/SearchEntityResultsTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml index cc6f202272e3b..59ca14680fb13 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/SearchEntityResultsTest.xml @@ -676,6 +676,13 @@ <magentoCLI command="indexer:reindex" stepKey="reindex"/> <magentoCLI command="cache:flush" stepKey="flushCache"/> </before> + <after> + <deleteData createDataKey="attributeSet" stepKey="deleteAttributeSet"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> + </after> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="goToFrontPage"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="searchStorefront"> <argument name="phrase" value="$createConfigProduct.name$"/> 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/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/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/StorefrontCheckoutWithSpecialPriceProductsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml index a9db81620d329..3f286df8337de 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutWithSpecialPriceProductsTest.xml @@ -102,6 +102,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" 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/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml index 34264e5982651..d302289b27f19 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromMiniShoppingCartTest.xml @@ -72,6 +72,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" 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/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml index b800ef758d65e..e544cbb497f2d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutUsingFreeShippingAndTaxesTest.xml @@ -109,6 +109,9 @@ <createData entity="DefaultShippingMethodsConfig" stepKey="defaultShippingMethodsConfig"/> <createData entity="DefaultMinimumOrderAmount" stepKey="defaultMinimumOrderAmount"/> <actionGroup ref="logout" 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/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/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml index 98cb03916bdab..4288684e53d27 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckConfigurableProductAttributeValueUniquenessTest.xml @@ -34,6 +34,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" 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..0b3d013660b6e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckResultsOfColorAndOtherFiltersTest.xml @@ -110,6 +110,9 @@ <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductsGridFilter"/> <!-- Log out --> <actionGroup ref="logout" 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..92a6dcad27b30 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCheckValidatorConfigurableProductTest.xml @@ -44,6 +44,9 @@ <argument name="ProductAttribute" value="productDropDownAttribute"/> </actionGroup> <actionGroup ref="logout" 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/AdminConfigurableProductDeleteTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml index 83e428b454c46..68afa17c4d539 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductDeleteTest.xml @@ -70,6 +70,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> <!-- assert product visible in storefront --> @@ -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..fc1f6dad36345 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductLongSkuTest.xml @@ -53,6 +53,9 @@ <!--Clean up category--> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" 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..48a33bfd14d9c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductOutOfStockTest.xml @@ -83,6 +83,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> <!-- Check to make sure that the configurable product shows up as in stock --> @@ -204,6 +207,9 @@ <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 --> @@ -306,6 +312,9 @@ <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..a73a7082502d8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductSearchTest.xml @@ -73,6 +73,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> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="goToProductList"/> @@ -152,6 +155,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> <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..e95a73dcebba0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateAttributeTest.xml @@ -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 --> @@ -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..1eb1d8df6030c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminConfigurableProductUpdateTest.xml @@ -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--> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml index f64ba4a63cec9..d3db180cb7999 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithDisabledChildrenProductsTest.xml @@ -54,6 +54,9 @@ <!-- Log out --> <actionGroup ref="logout" 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..37d5d515bb9e0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithImagesTest.xml @@ -57,6 +57,9 @@ <!-- Log out --> <actionGroup ref="logout" 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..299fbca412fac 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDisplayOutOfStockProductsTest.xml @@ -77,6 +77,9 @@ <!-- Log out --> <actionGroup ref="logout" 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..0aa0f22d6af2e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithThreeProductDontDisplayOutOfStockProductsTest.xml @@ -76,6 +76,9 @@ <!-- Log out --> <actionGroup ref="logout" 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..a2cd949a77d13 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminCreateConfigurableProductWithTierPriceForOneItemTest.xml @@ -65,6 +65,9 @@ <!-- Log out --> <actionGroup ref="logout" 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/AdminProductTypeSwitchingOnEditingTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml index f1535d62861ac..f441579a6ef42 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/AdminProductTypeSwitchingOnEditingTest.xml @@ -44,6 +44,9 @@ </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <actionGroup ref="logout" 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"/> @@ -148,6 +151,9 @@ </actionGroup> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="clearProductFilters"/> <actionGroup ref="logout" 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..7bb8661627b8c 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/ConfigurableProductPriceAdditionalStoreViewTest.xml @@ -78,6 +78,8 @@ <argument name="websiteName" value="Second Website"/> </actionGroup> <actionGroup ref="logout" 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..3d797e62c806a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/EndToEndB2CLoggedInUserTest.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 --> 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/NoOptionAvailableToConfigureDisabledProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml index 5224cc6a9cced..0e46027a69378 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml @@ -103,6 +103,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCustomer" stepKey="deleteCreatedCustomer"/> <actionGroup ref="logout" 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/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/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml index 9d7807c543def..1d699e01db9d0 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductCategoryViewChildOnlyTest.xml @@ -95,6 +95,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> <deleteData createDataKey="secondCategory" stepKey="deleteSecondCategory"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <actionGroup ref="LoginAsAdmin" stepKey="login"/> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml index 294ab9fd0664d..a0f3689b9c170 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductChildSearchTest.xml @@ -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..5d5481938f404 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontConfigurableProductDetailsTest.xml @@ -220,6 +220,9 @@ <deleteData createDataKey="createSecondAttribute" stepKey="deleteSecondAttribute"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> <actionGroup ref="logout" 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/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml index 7828478bc963e..cf7adafa82020 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontSortingByPriceForConfigurableWithCatalogRuleAppliedTest.xml @@ -117,6 +117,9 @@ <argument name="option" value="No"/> </actionGroup> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> + + <!-- 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..adaa302a23a52 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/StorefrontVerifyConfigurableProductLayeredNavigationTest.xml @@ -117,6 +117,9 @@ <deleteData createDataKey="createConfigChildProduct3" stepKey="deleteConfigChildProduct3"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteAttribute"/> <actionGroup ref="logout" 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/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontClearAllCompareProductsTest.xml index 40b05153f1a74..8651c9b4db62e 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 --> @@ -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/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml index 6a2f6ca60acf4..f5e8c91c31950 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminCheckThatSomeAttributesChangedValueToEmptyAfterImportTest.xml @@ -42,6 +42,9 @@ <!--Delete attribute--> <deleteData createDataKey="productAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" 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/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/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml index ccb724e8bf199..29f14185a0518 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontProductWithMapAssignedConfigProductIsCorrectTest.xml @@ -105,6 +105,9 @@ <createData entity="MsrpDisableMAP" stepKey="disableMAP"/> <actionGroup ref="logout" 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/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/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml index 6d9f35efc7903..df3a1a2b91219 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml @@ -72,6 +72,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/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml index b303364bbf324..5883d044e95a0 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCancelTheCreatedOrderWithCheckMoneyOrderPaymentMethodTest.xml @@ -108,6 +108,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" 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/AdminCreateCreditMemoConfigurableProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml index 2a841b04bd647..766839a50a862 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoConfigurableProductTest.xml @@ -98,6 +98,9 @@ <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> <actionGroup ref="logout" 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"> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml index 65bba7512e228..dc269ff7a2f98 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminSubmitConfigurableProductOrderTest.xml @@ -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/CreateOrderFromEditCustomerPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml index 0fcfa483f1adf..5d017cc0caab8 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateOrderFromEditCustomerPageTest.xml @@ -90,6 +90,9 @@ <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomerIndexPage"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearCustomerGridFilter"/> <actionGroup ref="logout" 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/MoveConfigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml index 980d5cc82b93d..27b0952781250 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml @@ -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..65c631b95f5c2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml @@ -66,6 +66,9 @@ <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/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml index aed7447050e5f..c7c08914fea4b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveRecentlyViewedConfigurableProductOnOrderPageTest.xml @@ -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/StorefrontPrintOrderGuestTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml index 31f3449866984..4369fa8a94101 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontPrintOrderGuestTest.xml @@ -226,6 +226,9 @@ <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="logout" 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/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml index ec9246f7c33bd..6db1c4f96796f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/CartPriceRuleForConfigurableProductTest.xml @@ -86,7 +86,10 @@ <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> <deleteData createDataKey="createCategory" stepKey="deleteApiCategory"/> - <actionGroup ref="logout" stepKey="logout"/> + <actionGroup ref="logout" 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/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 8a2683af83dc1..9666fd4211491 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -25,6 +25,9 @@ <after> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- 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" --> diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml index 6a718ebdfcf0f..bb0a3c40c21f1 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontDeleteConfigurableProductFromWishlistTest.xml @@ -118,6 +118,9 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteProductAttribute"/> <actionGroup ref="logout" stepKey="logout"/> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <actionGroup ref="CliRunReindexUsingCronJobsActionGroup" stepKey="reindexInvalidatedIndices"/> </after> <!-- 1. Login as a customer --> From 873bdcab4150035ed3cd76d656881b13a60f7aa8 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 3 Feb 2020 12:47:27 +0200 Subject: [PATCH 431/666] MC-30789: GTM is not trigged without Page Reload --- app/code/Magento/Cookie/view/frontend/web/js/notices.js | 1 + 1 file changed, 1 insertion(+) 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..9c51a49187c32 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('ga:init'); } else { window.location.href = this.options.noCookiesUrl; } From ed51b40914b99562ed9125c225694b3bd48af418 Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Mon, 3 Feb 2020 13:03:06 +0100 Subject: [PATCH 432/666] Use Order Entity ID instead of Order Increment ID --- .../Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml | 1 + 1 file changed, 1 insertion(+) 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"/> From 40311e95917e0631ea43834866b969e290cf667e Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Mon, 3 Feb 2020 14:26:10 +0200 Subject: [PATCH 433/666] Cover unit test --- .../Sold/Collection/CollectionTest.php | 144 +++++++++++++++--- 1 file changed, 123 insertions(+), 21 deletions(-) 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()); } } From 2d414e7bcb586afdeda9638939d1da341309d9c5 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Mon, 3 Feb 2020 15:00:51 +0200 Subject: [PATCH 434/666] MC-24930: Admin: Edit product Attribute --- .../Attribute/DataProvider/Decimal.php | 134 +++++ .../Attribute/DataProvider/MediaImage.php | 75 +++ .../Product/Attribute/DataProvider/Price.php | 59 --- .../AbstractAttributeDataWithOptions.php | 63 +++ .../AbstractBaseAttributeData.php | 176 ++++++- .../Eav/Model/Attribute/DataProvider/Date.php | 95 ++++ .../Model/Attribute/DataProvider/DropDown.php | 74 +++ .../Attribute/DataProvider/MultipleSelect.php | 74 +++ .../Eav/Model/Attribute/DataProvider/Text.php | 76 +++ .../Model/Attribute/DataProvider/TextArea.php | 86 ++++ .../Attribute/DataProvider/TextEditor.php | 87 ++++ .../Model/Attribute/DataProvider/YesNo.php | 76 +++ .../GetEntityIdByAttributeId.php | 16 +- .../Attribute/DataProvider/TextSwatch.php | 136 +++++ .../Attribute/DataProvider/VisualSwatch.php | 130 +++++ .../DataProvider/FixedProductTax.php | 75 +++ .../AbstractSaveAttributeTest.php | 41 +- .../{PriceTest.php => DecimalTest.php} | 9 +- .../Save/InputType/MediaImageTest.php | 7 +- .../Update/AbstractUpdateAttributeTest.php | 472 ++++++++++++++++++ .../Update/InputType/DecimalTest.php | 67 +++ .../Update/InputType/MediaImageTest.php | 67 +++ .../_files/product_text_editor_attribute.php | 55 ++ ...product_text_editor_attribute_rollback.php | 26 + .../Attribute/Save/InputType/DateTest.php | 7 +- .../Attribute/Save/InputType/DropDownTest.php | 7 +- .../Save/InputType/MultipleSelectTest.php | 7 +- .../Attribute/Save/InputType/TextAreaTest.php | 7 +- .../Save/InputType/TextEditorTest.php | 7 +- .../Attribute/Save/InputType/TextTest.php | 7 +- .../Attribute/Save/InputType/YesNoTest.php | 7 +- .../Attribute/Update/InputType/DateTest.php | 67 +++ .../Update/InputType/DropDownTest.php | 82 +++ .../Update/InputType/MultipleSelectTest.php | 82 +++ .../Update/InputType/TextAreaTest.php | 67 +++ .../Update/InputType/TextEditorTest.php | 67 +++ .../Attribute/Update/InputType/TextTest.php | 67 +++ .../Attribute/Update/InputType/YesNoTest.php | 67 +++ .../Save/InputType/TextSwatchTest.php | 7 +- .../Save/InputType/VisualSwatchTest.php | 7 +- .../AbstractUpdateSwatchAttributeTest.php | 146 ++++++ .../Update/InputType/TextSwatchTest.php | 91 ++++ .../Update/InputType/VisualSwatchTest.php | 91 ++++ ...oduct_visual_swatch_attribute_rollback.php | 3 +- .../Save/InputType/FixedProductTaxTest.php | 7 +- .../Update/InputType/FixedProductTaxTest.php | 67 +++ 46 files changed, 3014 insertions(+), 129 deletions(-) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Decimal.php delete mode 100644 dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Price.php rename dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/{InputType => }/AbstractSaveAttributeTest.php (86%) rename dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/{PriceTest.php => DecimalTest.php} (79%) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateAttributeTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/DecimalTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/MediaImageTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DropDownTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/MultipleSelectTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextAreaTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextEditorTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/YesNoTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateSwatchAttributeTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/TextSwatchTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/VisualSwatchTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Update/InputType/FixedProductTaxTest.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Decimal.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Decimal.php new file mode 100644 index 0000000000000..ad72f2d197794 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Decimal.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider; + +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\TestFramework\Eav\Model\Attribute\DataProvider\AbstractBaseAttributeData; +use Magento\Store\Model\Store; +use Magento\Catalog\Model\Product\Attribute\Backend\Price as BackendPrice; + +/** + * Product attribute data for attribute with input type weee. + */ +class Decimal extends AbstractBaseAttributeData +{ + /** + * @inheritdoc + */ + public function __construct() + { + parent::__construct(); + $this->defaultAttributePostData['is_filterable'] = '0'; + $this->defaultAttributePostData['is_filterable_in_search'] = '0'; + $this->defaultAttributePostData['used_for_sort_by'] = '0'; + } + + /** + * @inheritdoc + */ + public function getAttributeData(): array + { + $result = parent::getAttributeData(); + unset($result["{$this->getFrontendInput()}_with_default_value"]); + unset($result["{$this->getFrontendInput()}_without_default_value"]); + + return $result; + } + + /** + * @inheritdoc + */ + public function getAttributeDataWithCheckArray(): array + { + $result = parent::getAttributeDataWithCheckArray(); + unset($result["{$this->getFrontendInput()}_with_default_value"]); + unset($result["{$this->getFrontendInput()}_without_default_value"]); + + return $result; + } + + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'decimal_attribute', + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + protected function getFrontendInput(): string + { + return 'price'; + } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Decimal Attribute Update', + ], + 'frontend_input' => 'price', + 'is_required' => '1', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '1', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Decimal Attribute Update', + 'attribute_code' => 'decimal_attribute', + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'default_value' => null, + 'frontend_class' => null, + 'is_user_defined' => '1', + 'backend_type' => 'decimal', + 'backend_model' => BackendPrice::class, + ] + ); + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/MediaImage.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/MediaImage.php index dd706ab29c326..7ae0169efa497 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/MediaImage.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/MediaImage.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider; +use Magento\Catalog\Model\Product\Attribute\Frontend\Image; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; use Magento\TestFramework\Eav\Model\Attribute\DataProvider\AbstractBaseAttributeData; /** @@ -47,6 +50,27 @@ public function getAttributeDataWithCheckArray(): array return $result; } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'image_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -54,4 +78,55 @@ protected function getFrontendInput(): string { return 'media_image'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Decimal Attribute Update', + ], + 'frontend_input' => 'media_image', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Decimal Attribute Update', + 'is_required' => '0', + 'attribute_code' => 'image_attribute', + 'default_value' => null, + 'is_unique' => '0', + 'frontend_class' => null, + 'is_searchable' => '0', + 'search_weight' => '1', + 'is_visible_in_advanced_search' => '0', + 'is_comparable' => '0', + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_used_for_promo_rules' => '0', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '0', + 'used_in_product_listing' => '1', + 'used_for_sort_by' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'varchar', + 'frontend_model' => Image::class, + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Price.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Price.php deleted file mode 100644 index 04ee6bb0a5740..0000000000000 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Attribute/DataProvider/Price.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider; - -use Magento\TestFramework\Eav\Model\Attribute\DataProvider\AbstractBaseAttributeData; - -/** - * Product attribute data for attribute with input type weee. - */ -class Price extends AbstractBaseAttributeData -{ - /** - * @inheritdoc - */ - public function __construct() - { - parent::__construct(); - $this->defaultAttributePostData['is_filterable'] = '0'; - $this->defaultAttributePostData['is_filterable_in_search'] = '0'; - $this->defaultAttributePostData['used_for_sort_by'] = '0'; - } - - /** - * @inheritdoc - */ - public function getAttributeData(): array - { - $result = parent::getAttributeData(); - unset($result["{$this->getFrontendInput()}_with_default_value"]); - unset($result["{$this->getFrontendInput()}_without_default_value"]); - - return $result; - } - - /** - * @inheritdoc - */ - public function getAttributeDataWithCheckArray(): array - { - $result = parent::getAttributeDataWithCheckArray(); - unset($result["{$this->getFrontendInput()}_with_default_value"]); - unset($result["{$this->getFrontendInput()}_without_default_value"]); - - return $result; - } - - /** - * @inheritdoc - */ - protected function getFrontendInput(): string - { - return 'price'; - } -} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractAttributeDataWithOptions.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractAttributeDataWithOptions.php index 8f25651e2e036..affd063d99ab5 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractAttributeDataWithOptions.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractAttributeDataWithOptions.php @@ -7,6 +7,8 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Store\Model\Store; + /** * Base POST data for create attribute with options. */ @@ -72,6 +74,67 @@ public function getAttributeDataWithCheckArray(): array return $result; } + /** + * Return product attribute data set for update attribute options. + * + * @return array + */ + public function getUpdateOptionsProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return [ + "{$frontendInput}_update_options" => [ + 'post_data' => [ + 'options_array' => [ + 'option_1' => [ + 'order' => '5', + 'value' => [ + Store::DEFAULT_STORE_ID => 'Option 1 Admin', + 'default' => 'Option 1 Store 1', + 'fixture_second_store' => 'Option 1 Store 2', + 'fixture_third_store' => 'Option 1 Store 3', + ], + 'delete' => '', + ], + 'option_2' => [ + 'order' => '6', + 'value' => [ + Store::DEFAULT_STORE_ID => 'Option 2 Admin', + 'default' => 'Option 2 Store 1', + 'fixture_second_store' => 'Option 2 Store 2', + 'fixture_third_store' => 'Option 2 Store 3', + ], + 'delete' => '', + 'default' => 1, + ], + ], + ], + ], + "{$frontendInput}_delete_options" => [ + 'post_data' => [ + 'options_array' => [ + 'option_1' => [ + 'value' => [], + 'delete' => '', + ], + 'option_2' => [ + 'value' => [], + 'delete' => '1', + ], + 'option_3' => [ + 'value' => [], + 'delete' => '', + ], + 'option_4' => [ + 'value' => [], + 'delete' => '1', + ], + ], + ], + ], + ]; + } + /** * Return attribute options data. * diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractBaseAttributeData.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractBaseAttributeData.php index af9e58d02fb5a..cd93e57a849cf 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractBaseAttributeData.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/AbstractBaseAttributeData.php @@ -8,6 +8,7 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; use Magento\Store\Model\Store; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; /** * Base POST data for create attribute. @@ -28,7 +29,7 @@ abstract class AbstractBaseAttributeData 'dropdown_attribute_validation' => '', 'dropdown_attribute_validation_unique' => '', 'attribute_code' => '', - 'is_global' => '0', + 'is_global' => ScopedAttributeInterface::SCOPE_STORE, 'default_value_text' => '', 'default_value_yesno' => '0', 'default_value_date' => '', @@ -68,10 +69,10 @@ public function getAttributeData(): array $this->defaultAttributePostData, ], "{$this->getFrontendInput()}_with_global_scope" => [ - array_merge($this->defaultAttributePostData, ['is_global' => '1']), + array_merge($this->defaultAttributePostData, ['is_global' => ScopedAttributeInterface::SCOPE_GLOBAL]), ], "{$this->getFrontendInput()}_with_website_scope" => [ - array_merge($this->defaultAttributePostData, ['is_global' => '2']), + array_merge($this->defaultAttributePostData, ['is_global' => ScopedAttributeInterface::SCOPE_WEBSITE]), ], "{$this->getFrontendInput()}_with_attribute_code" => [ array_merge($this->defaultAttributePostData, ['attribute_code' => 'test_custom_attribute_code']), @@ -143,19 +144,19 @@ public function getAttributeDataWithCheckArray(): array "{$this->getFrontendInput()}_with_store_view_scope" => [ [ 'attribute_code' => 'test_attribute_name', - 'is_global' => '0', + 'is_global' => ScopedAttributeInterface::SCOPE_STORE, ], ], "{$this->getFrontendInput()}_with_global_scope" => [ [ 'attribute_code' => 'test_attribute_name', - 'is_global' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, ], ], "{$this->getFrontendInput()}_with_website_scope" => [ [ 'attribute_code' => 'test_attribute_name', - 'is_global' => '2', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, ], ], "{$this->getFrontendInput()}_with_attribute_code" => [ @@ -215,10 +216,173 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * Return product attribute data set for update attribute. + * + * @return array + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return [ + "{$frontendInput}_update_all_fields" => [ + 'post_data' => $this->getUpdatePostData(), + 'expected_data' => $this->getUpdateExpectedData(), + ], + "{$frontendInput}_other_is_user_defined" => [ + 'post_data' => [ + 'is_user_defined' => '2', + ], + 'expected_data' => [ + 'is_user_defined' => '1', + ], + ], + "{$frontendInput}_with_is_global_null" => [ + 'post_data' => [ + 'is_global' => null, + ], + 'expected_data' => [ + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + ], + ], + "{$frontendInput}_is_visible_in_advanced_search" => [ + 'post_data' => [ + 'is_searchable' => '0', + 'is_visible_in_advanced_search' => '1', + ], + 'expected_data' => [ + 'is_searchable' => '0', + 'is_visible_in_advanced_search' => '0', + ], + ], + "{$frontendInput}_update_with_attribute_set" => [ + 'post_data' => [ + 'set' => '4', + 'new_attribute_set_name' => 'Text Attribute Set', + 'group' => 'text_attribute_group', + 'groupName' => 'Text Attribute Group', + 'groupSortOrder' => '1', + ], + 'expected_data' => [], + ], + ]; + } + + /** + * Return product attribute data set with error message for update attribute. + * + * @return array + */ + public function getUpdateProviderWithErrorMessage(): array + { + $frontendInput = $this->getFrontendInput(); + return [ + "{$frontendInput}_same_attribute_set_name" => [ + 'post_data' => [ + 'set' => '4', + 'new_attribute_set_name' => 'Default', + ], + 'error_message' => (string)__('An attribute set named \'Default\' already exists.'), + ], + "{$frontendInput}_empty_set_id" => [ + 'post_data' => [ + 'set' => '', + 'new_attribute_set_name' => 'Text Attribute Set', + ], + 'error_message' => (string)__('Something went wrong while saving the attribute.'), + ], + "{$frontendInput}_nonexistent_attribute_id" => [ + 'post_data' => [ + 'attribute_id' => 9999, + ], + 'error_message' => (string)__('This attribute no longer exists.'), + ], + "{$frontendInput}_attribute_other_entity_type" => [ + 'post_data' => [ + 'attribute_id' => 45, + ], + 'error_message' => (string)__('We can\'t update the attribute.'), + ], + ]; + } + + /** + * Return product attribute data set for update attribute frontend labels. + * + * @return array + */ + public function getUpdateFrontendLabelsProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return [ + "{$frontendInput}_update_frontend_label" => [ + 'post_data' => [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Test Attribute Update', + 'default' => 'Default Store Update', + 'fixture_second_store' => 'Second Store Update', + 'fixture_third_store' => 'Third Store Update', + ] + ], + 'expected_data' => [ + 'frontend_label' => 'Test Attribute Update', + 'store_labels' => [ + 'default' => 'Default Store Update', + 'fixture_second_store' => 'Second Store Update', + 'fixture_third_store' => 'Third Store Update', + ], + ], + ], + "{$frontendInput}_remove_frontend_label" => [ + 'post_data' => [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Test Attribute Update', + 'default' => 'Default Store Update', + 'fixture_second_store' => '', + 'fixture_third_store' => '', + ] + ], + 'expected_data' => [ + 'frontend_label' => 'Test Attribute Update', + 'store_labels' => [ + 'default' => 'Default Store Update', + ], + ], + ], + "{$frontendInput}_with_frontend_label_string" => [ + 'post_data' => [ + 'frontend_label' => 'Test Attribute Update', + ], + 'expected_data' => [ + 'frontend_label' => 'Test Attribute Update', + 'store_labels' => [ + 'default' => 'Default Store View', + 'fixture_second_store' => 'Fixture Second Store', + 'fixture_third_store' => 'Fixture Third Store', + ], + ], + ], + ]; + } + /** * Return attribute frontend input. * * @return string */ abstract protected function getFrontendInput(): string; + + /** + * Return post data for attribute update. + * + * @return array + */ + abstract protected function getUpdatePostData(): array; + + /** + * Return expected data for attribute update. + * + * @return array + */ + abstract protected function getUpdateExpectedData(): array; } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php index 7a6f8ee41c1f8..3c6caddfdb95c 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with input type date. */ @@ -56,6 +59,46 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'date_attribute', + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + public function getUpdateProviderWithErrorMessage(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProviderWithErrorMessage(), + [ + "{$frontendInput}_wrong_default_value" => [ + 'post_data' => [ + 'default_value_date' => '2019//12//12', + ], + 'error_message' => (string)__('The default date is invalid. Verify the date and try again.'), + ], + ] + ); + } + /** * @inheritdoc */ @@ -63,4 +106,56 @@ protected function getFrontendInput(): string { return 'date'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Date Attribute Update', + ], + 'frontend_input' => 'date', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_date' => '12/29/2019', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_date']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Date Attribute Update', + 'attribute_code' => 'date_attribute', + 'default_value' => '2019-12-29 00:00:00', + 'frontend_class' => null, + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'datetime', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DropDown.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DropDown.php index 3c1acb5a33a54..8366b13760795 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DropDown.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DropDown.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with input type dropdown. */ @@ -22,6 +25,27 @@ public function __construct() $this->defaultAttributePostData['swatch_input_type'] = 'dropdown'; } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'dropdown_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -29,4 +53,54 @@ protected function getFrontendInput(): string { return 'select'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Drop-Down Attribute Update', + ], + 'frontend_input' => 'select', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '1', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '0', + 'is_visible_on_front' => '0', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Drop-Down Attribute Update', + 'attribute_code' => 'dropdown_attribute', + 'default_value' => null, + 'frontend_class' => null, + 'is_user_defined' => '1', + 'backend_type' => 'varchar', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/MultipleSelect.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/MultipleSelect.php index 5fb5f745aebdc..4d72f5b316ea0 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/MultipleSelect.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/MultipleSelect.php @@ -7,11 +7,35 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with input type multiple select. */ class MultipleSelect extends AbstractAttributeDataWithOptions { + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'multiselect_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -19,4 +43,54 @@ protected function getFrontendInput(): string { return 'multiselect'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Multiselect Attribute Update', + ], + 'frontend_input' => 'multiselect', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '1', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '0', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Multiselect Attribute Update', + 'attribute_code' => 'multiselect_attribute', + 'default_value' => null, + 'frontend_class' => null, + 'used_for_sort_by' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'varchar', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Text.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Text.php index 5b37248e27361..654e31a0f4528 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Text.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Text.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with input type text. */ @@ -64,6 +67,27 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'varchar_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'varchar_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -71,4 +95,56 @@ protected function getFrontendInput(): string { return 'text'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Varchar Attribute Update', + ], + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_text' => 'Varchar Attribute Default', + 'is_unique' => '1', + 'frontend_class' => 'validate-alphanum', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '0', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_text']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Varchar Attribute Update', + 'frontend_input' => 'text', + 'attribute_code' => 'varchar_attribute', + 'default_value' => 'Varchar Attribute Default', + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'varchar', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextArea.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextArea.php index 7588b12700272..2b9414fe01390 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextArea.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextArea.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with text area input type. */ @@ -30,6 +33,36 @@ public function getAttributeData(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'text_attribute', + ], + ], + "{$frontendInput}_change_frontend_input" => [ + 'post_data' => [ + 'frontend_input' => 'texteditor', + ], + 'expected_data' => [ + 'frontend_input' => 'textarea', + 'is_wysiwyg_enabled' => '1' + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -37,4 +70,57 @@ protected function getFrontendInput(): string { return 'textarea'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Text Attribute Update', + ], + 'frontend_input' => 'textarea', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_textarea' => 'Text Attribute Default', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_textarea']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Text Attribute Update', + 'attribute_code' => 'text_attribute', + 'default_value' => 'Text Attribute Default', + 'frontend_class' => null, + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'used_for_sort_by' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'text', + 'is_wysiwyg_enabled' => '0', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextEditor.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextEditor.php index d7a6276c1720f..282031e4377a5 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextEditor.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/TextEditor.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with text editor input type. */ @@ -116,6 +119,36 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'text_editor_attribute', + ], + ], + "{$frontendInput}_change_frontend_input" => [ + 'post_data' => [ + 'frontend_input' => 'textarea', + ], + 'expected_data' => [ + 'frontend_input' => 'textarea', + 'is_wysiwyg_enabled' => '0' + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -123,4 +156,58 @@ protected function getFrontendInput(): string { return 'texteditor'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Text Editor Attribute Update', + ], + 'frontend_input' => 'texteditor', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_textarea' => 'Text Editor Attribute Default', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '1', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_textarea']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Text Editor Attribute Update', + 'frontend_input' => 'textarea', + 'attribute_code' => 'text_editor_attribute', + 'default_value' => 'Text Editor Attribute Default', + 'frontend_class' => null, + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'text', + 'is_wysiwyg_enabled' => '1', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/YesNo.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/YesNo.php index 8fece70f0273c..28428b38be009 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/YesNo.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/YesNo.php @@ -7,6 +7,9 @@ namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + /** * Product attribute data for attribute with yes/no input type. */ @@ -58,6 +61,27 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'boolean_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -65,4 +89,56 @@ protected function getFrontendInput(): string { return 'boolean'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Boolean Attribute Update', + ], + 'frontend_input' => 'boolean', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_yesno' => '1', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '0', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '0', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '0', + 'is_visible_on_front' => '0', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_yesno']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Boolean Attribute Update', + 'attribute_code' => 'boolean_attribute', + 'default_value' => '1', + 'frontend_class' => null, + 'is_user_defined' => '1', + 'backend_type' => 'int', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/ResourceModel/GetEntityIdByAttributeId.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/ResourceModel/GetEntityIdByAttributeId.php index edb75a5d8d1bd..76235b3392684 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/ResourceModel/GetEntityIdByAttributeId.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/ResourceModel/GetEntityIdByAttributeId.php @@ -33,16 +33,24 @@ public function __construct( * * @param int $setId * @param int $attributeId + * @param int|null $attributeGroupId * @return int|null */ - public function execute(int $setId, int $attributeId): ?int + public function execute(int $setId, int $attributeId, ?int $attributeGroupId = null): ?int { $select = $this->attributeSetResource->getConnection()->select() - ->from($this->attributeSetResource->getTable('eav_entity_attribute')) + ->from( + $this->attributeSetResource->getTable('eav_entity_attribute'), + 'entity_attribute_id' + ) ->where('attribute_set_id = ?', $setId) ->where('attribute_id = ?', $attributeId); - $result = $this->attributeSetResource->getConnection()->fetchOne($select); - return $result ? (int)$result : null; + if ($attributeGroupId !== null) { + $select->where('attribute_group_id = ?', $attributeGroupId); + } + $entityAttributeId = $this->attributeSetResource->getConnection()->fetchOne($select); + + return $entityAttributeId ? (int)$entityAttributeId : null; } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/TextSwatch.php b/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/TextSwatch.php index c63873469e2f8..bb705b5503c39 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/TextSwatch.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/TextSwatch.php @@ -7,7 +7,9 @@ namespace Magento\TestFramework\Swatches\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; use Magento\Swatches\Model\Swatch; +use Magento\Store\Model\Store; /** * Product attribute data for attribute with input type visual swatch. @@ -90,6 +92,88 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'text_swatch_attribute', + ], + ], + "{$frontendInput}_change_frontend_input_swatch_visual" => [ + 'post_data' => [ + 'frontend_input' => Swatch::SWATCH_TYPE_VISUAL_ATTRIBUTE_FRONTEND_INPUT, + 'update_product_preview_image' => '1', + 'use_product_image_for_swatch' => '1', + ], + 'expected_data' => [ + 'frontend_input' => 'select', + 'swatch_input_type' => Swatch::SWATCH_INPUT_TYPE_VISUAL, + 'update_product_preview_image' => '1', + 'use_product_image_for_swatch' => '1', + ], + ], + "{$frontendInput}_change_frontend_input_dropdown" => [ + 'post_data' => [ + 'frontend_input' => 'select', + ], + 'expected_data' => [ + 'frontend_input' => 'select', + 'swatch_input_type' => null, + 'update_product_preview_image' => null, + 'use_product_image_for_swatch' => null, + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + public function getUpdateOptionsProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateOptionsProvider(), + [ + "{$frontendInput}_update_options" => [ + 'post_data' => [ + 'options_array' => [ + 'option_1' => [ + 'order' => '4', + 'swatch' => [ + Store::DEFAULT_STORE_ID => 'Swatch 1 Admin', + 'default' => 'Swatch 1 Store 1', + 'fixture_second_store' => 'Swatch 1 Store 2', + 'fixture_third_store' => 'Swatch 1 Store 3', + ], + ], + 'option_2' => [ + 'order' => '5', + 'swatch' => [ + Store::DEFAULT_STORE_ID => 'Swatch 2 Admin', + 'default' => 'Swatch 2 Store 1', + 'fixture_second_store' => 'Swatch 2 Store 2', + 'fixture_third_store' => 'Swatch 2 Store 3', + ], + ], + ], + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -157,4 +241,56 @@ protected function getFrontendInput(): string { return Swatch::SWATCH_TYPE_TEXTUAL_ATTRIBUTE_FRONTEND_INPUT; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Text swatch attribute Update', + ], + 'frontend_input' => Swatch::SWATCH_TYPE_TEXTUAL_ATTRIBUTE_FRONTEND_INPUT, + 'is_required' => '1', + 'update_product_preview_image' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '1', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Text swatch attribute Update', + 'frontend_input' => 'select', + 'attribute_code' => 'text_swatch_attribute', + 'default_value' => null, + 'frontend_class' => null, + 'is_html_allowed_on_front' => '1', + 'is_user_defined' => '1', + 'backend_type' => 'int', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/VisualSwatch.php b/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/VisualSwatch.php index b5e32c40ef8a1..c5195d7d1d1a4 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/VisualSwatch.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Swatches/Model/Attribute/DataProvider/VisualSwatch.php @@ -7,7 +7,9 @@ namespace Magento\TestFramework\Swatches\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; use Magento\Swatches\Model\Swatch; +use Magento\Store\Model\Store; /** * Product attribute data for attribute with input type visual swatch. @@ -90,6 +92,81 @@ public function getAttributeDataWithCheckArray(): array ); } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'visual_swatch_attribute', + ], + ], + "{$frontendInput}_change_frontend_input_swatch_text" => [ + 'post_data' => [ + 'frontend_input' => Swatch::SWATCH_TYPE_TEXTUAL_ATTRIBUTE_FRONTEND_INPUT, + 'update_product_preview_image' => '1', + ], + 'expected_data' => [ + 'frontend_input' => 'select', + 'swatch_input_type' => Swatch::SWATCH_INPUT_TYPE_TEXT, + 'update_product_preview_image' => '1', + 'use_product_image_for_swatch' => 0, + ], + ], + "{$frontendInput}_change_frontend_input_dropdown" => [ + 'post_data' => [ + 'frontend_input' => 'select', + ], + 'expected_data' => [ + 'frontend_input' => 'select', + 'swatch_input_type' => null, + 'update_product_preview_image' => null, + 'use_product_image_for_swatch' => null, + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + public function getUpdateOptionsProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateOptionsProvider(), + [ + "{$frontendInput}_update_options" => [ + 'post_data' => [ + 'options_array' => [ + 'option_1' => [ + 'order' => '4', + 'swatch' => [ + Store::DEFAULT_STORE_ID => '#1a1a1a', + ], + ], + 'option_2' => [ + 'order' => '5', + 'swatch' => [ + Store::DEFAULT_STORE_ID => '#2b2b2b', + ], + ], + ], + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -148,4 +225,57 @@ protected function getFrontendInput(): string { return Swatch::SWATCH_TYPE_VISUAL_ATTRIBUTE_FRONTEND_INPUT; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Visual swatch attribute Update', + ], + 'frontend_input' => Swatch::SWATCH_TYPE_VISUAL_ATTRIBUTE_FRONTEND_INPUT, + 'is_required' => '1', + 'update_product_preview_image' => '1', + 'use_product_image_for_swatch' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_filterable' => '2', + 'is_filterable_in_search' => '1', + 'position' => '2', + 'is_used_for_promo_rules' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Visual swatch attribute Update', + 'frontend_input' => 'select', + 'attribute_code' => 'visual_swatch_attribute', + 'default_value' => null, + 'frontend_class' => null, + 'is_html_allowed_on_front' => '1', + 'is_user_defined' => '1', + 'backend_type' => 'int', + ] + ); + } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Weee/Model/Attribute/DataProvider/FixedProductTax.php b/dev/tests/integration/framework/Magento/TestFramework/Weee/Model/Attribute/DataProvider/FixedProductTax.php index 2f1f625ad48ac..ab0b214ccc101 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Weee/Model/Attribute/DataProvider/FixedProductTax.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Weee/Model/Attribute/DataProvider/FixedProductTax.php @@ -7,7 +7,10 @@ namespace Magento\TestFramework\Weee\Model\Attribute\DataProvider; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; use Magento\TestFramework\Eav\Model\Attribute\DataProvider\AbstractBaseAttributeData; +use Magento\Store\Model\Store; +use Magento\Weee\Model\Attribute\Backend\Weee\Tax; /** * Product attribute data for attribute with input type fixed product tax. @@ -47,6 +50,27 @@ public function getAttributeDataWithCheckArray(): array return $result; } + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'fixed_product_attribute', + ], + ], + ] + ); + } + /** * @inheritdoc */ @@ -54,4 +78,55 @@ protected function getFrontendInput(): string { return 'weee'; } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Fixed product tax Update', + ], + 'frontend_input' => 'weee', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Fixed product tax Update', + 'is_required' => '0', + 'attribute_code' => 'fixed_product_attribute', + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'default_value' => null, + 'is_unique' => '0', + 'frontend_class' => null, + 'is_searchable' => '0', + 'search_weight' => '1', + 'is_visible_in_advanced_search' => '0', + 'is_comparable' => '0', + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_used_for_promo_rules' => '0', + 'is_html_allowed_on_front' => '0', + 'is_visible_on_front' => '0', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'static', + 'backend_model' => Tax::class, + ] + ); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/AbstractSaveAttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/AbstractSaveAttributeTest.php similarity index 86% rename from dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/AbstractSaveAttributeTest.php rename to dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/AbstractSaveAttributeTest.php index d0f1256f1fdb7..91650d4b7444e 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/AbstractSaveAttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/AbstractSaveAttributeTest.php @@ -5,11 +5,10 @@ */ declare(strict_types=1); -namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType; +namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save; -use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Api\ProductAttributeOptionManagementInterface; -use Magento\Eav\Api\AttributeRepositoryInterface; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Eav\Api\Data\AttributeInterface; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\App\Request\Http as HttpRequest; @@ -22,27 +21,21 @@ /** * Base create and assert attribute data. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractSaveAttributeTest extends AbstractBackendController { - /** - * @var AttributeRepositoryInterface - */ - protected $attributeRepository; + /** @var ProductAttributeRepositoryInterface */ + protected $productAttributeRepository; - /** - * @var Escaper - */ + /** @var Escaper */ protected $escaper; - /** - * @var Json - */ + /** @var Json */ protected $jsonSerializer; - /** - * @var ProductAttributeOptionManagementInterface - */ + /** @var ProductAttributeOptionManagementInterface */ protected $productAttributeOptionManagement; /** @@ -51,12 +44,12 @@ abstract class AbstractSaveAttributeTest extends AbstractBackendController protected function setUp() { parent::setUp(); - $this->attributeRepository = $this->_objectManager->get(AttributeRepositoryInterface::class); $this->escaper = $this->_objectManager->get(Escaper::class); $this->jsonSerializer = $this->_objectManager->get(Json::class); $this->productAttributeOptionManagement = $this->_objectManager->get( ProductAttributeOptionManagementInterface::class ); + $this->productAttributeRepository = $this->_objectManager->get(ProductAttributeRepositoryInterface::class); } /** @@ -73,15 +66,15 @@ protected function createAttributeUsingDataAndAssert(array $attributeData, array if (isset($attributeData['serialized_options_arr'])) { $attributeData['serialized_options'] = $this->serializeOptions($attributeData['serialized_options_arr']); } - $this->createAttributeViaController($attributeData); + $this->dispatchAttributeSave($attributeData); $this->assertSessionMessages( $this->equalTo([(string)__('You saved the product attribute.')]), MessageInterface::TYPE_SUCCESS ); try { - $attribute = $this->attributeRepository->get(ProductAttributeInterface::ENTITY_TYPE_CODE, $attributeCode); + $attribute = $this->productAttributeRepository->get($attributeCode); $this->assertAttributeData($attribute, $attributeData, $checkArray); - $this->attributeRepository->delete($attribute); + $this->productAttributeRepository->delete($attribute); } catch (NoSuchEntityException $e) { $this->fail("Attribute with code {$attributeCode} was not created."); } @@ -101,15 +94,15 @@ protected function createAttributeUsingDataWithErrorAndAssert(array $attributeDa ) { $attributeData['serialized_options'] = $this->serializeOptions($attributeData['serialized_options_arr']); } - $this->createAttributeViaController($attributeData); + $this->dispatchAttributeSave($attributeData); $this->assertSessionMessages( $this->equalTo([$this->escaper->escapeHtml($errorMessage)]), MessageInterface::TYPE_ERROR ); $attributeCode = $this->getAttributeCodeFromAttributeData($attributeData); try { - $attribute = $this->attributeRepository->get(ProductAttributeInterface::ENTITY_TYPE_CODE, $attributeCode); - $this->attributeRepository->delete($attribute); + $attribute = $this->productAttributeRepository->get($attributeCode); + $this->productAttributeRepository->delete($attribute); } catch (NoSuchEntityException $e) { //Attribute already deleted. } @@ -191,7 +184,7 @@ private function getAttributeCodeFromAttributeData(array $attributeData): string * @param array $attributeData * @return void */ - private function createAttributeViaController(array $attributeData): void + private function dispatchAttributeSave(array $attributeData): void { $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->getRequest()->setPostValue($attributeData); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/PriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/DecimalTest.php similarity index 79% rename from dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/PriceTest.php rename to dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/DecimalTest.php index fb71f0a4d9d76..943f33b9c1800 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/DecimalTest.php @@ -7,17 +7,20 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; + /** * Test cases related to create attribute with input type price. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ -class PriceTest extends AbstractSaveAttributeTest +class DecimalTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Price::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Decimal::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -31,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Price::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Decimal::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/MediaImageTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/MediaImageTest.php index f8adac2872773..c6500e03fa327 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/MediaImageTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save/InputType/MediaImageTest.php @@ -7,17 +7,20 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; + /** * Test cases related to create attribute with input type media image. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class MediaImageTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -31,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateAttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateAttributeTest.php new file mode 100644 index 0000000000000..60702d83bf4f7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateAttributeTest.php @@ -0,0 +1,472 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update; + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Attribute as AttributeResource; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option as OptionResource; +use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory as OptionCollectionFactory; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Escaper; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Eav\Model\GetAttributeGroupByName; +use Magento\TestFramework\Eav\Model\GetAttributeSetByName; +use Magento\TestFramework\Eav\Model\ResourceModel\GetEntityIdByAttributeId; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Base update and assert attribute data. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +abstract class AbstractUpdateAttributeTest extends AbstractBackendController +{ + /** @var ProductAttributeRepositoryInterface */ + protected $productAttributeRepository; + + /** @var Escaper */ + protected $escaper; + + /** @var Json */ + protected $jsonSerializer; + + /** @var GetAttributeSetByName */ + private $getAttributeSetByName; + + /** @var GetAttributeGroupByName */ + private $getAttributeGroupByName; + + /** @var GetEntityIdByAttributeId */ + private $getEntityIdByAttributeId; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var OptionCollectionFactory */ + private $optionCollectionFactory; + + /** @var OptionResource */ + private $attributeOptionResource; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->escaper = $this->_objectManager->get(Escaper::class); + $this->jsonSerializer = $this->_objectManager->get(Json::class); + $this->productAttributeRepository = $this->_objectManager->get(ProductAttributeRepositoryInterface::class); + $this->getAttributeSetByName = $this->_objectManager->get(GetAttributeSetByName::class); + $this->getAttributeGroupByName = $this->_objectManager->get(GetAttributeGroupByName::class); + $this->getEntityIdByAttributeId = $this->_objectManager->get(GetEntityIdByAttributeId::class); + $this->storeManager = $this->_objectManager->get(StoreManagerInterface::class); + $this->optionCollectionFactory = $this->_objectManager->get(OptionCollectionFactory::class); + $this->attributeOptionResource = $this->_objectManager->get(OptionResource::class); + } + + /** + * Updates attribute frontend labels on stores for a given attribute type. + * + * @param string $attributeCode + * @param array $postData + * @param array $expectedData + * @return void + */ + protected function processUpdateFrontendLabelOnStores( + string $attributeCode, + array $postData, + array $expectedData + ): void { + $this->setAttributeStorelabels($attributeCode); + if (is_array($postData['frontend_label'])) { + $postData['frontend_label'] = $this->prepareStoresData($postData['frontend_label']); + } + $expectedData['store_labels'] = $this->prepareStoresData($expectedData['store_labels']); + + $this->_objectManager->removeSharedInstance(AttributeResource::class); + $this->updateAttributeUsingData($attributeCode, $postData); + $this->assertUpdateAttributeProcess($attributeCode, $postData, $expectedData); + } + + /** + * Updates attribute options on stores for a given attribute type. + * + * @param string $attributeCode + * @param array $postData + * @return void + */ + protected function processUpdateOptionsOnStores(string $attributeCode, array $postData): void + { + $optionsData = $this->prepareStoreOptionsArray($attributeCode, $postData['options_array']); + $optionsPostData = $this->prepareStoreOptionsPostData($optionsData); + $postData['serialized_options'] = $this->serializeOptions($optionsPostData); + $expectedData = $this->prepareStoreOptionsExpectedData($optionsData); + + $this->_objectManager->removeSharedInstance(AttributeResource::class); + $this->updateAttributeUsingData($attributeCode, $postData); + $this->assertUpdateAttributeProcess($attributeCode, $postData, $expectedData); + } + + /** + * Prepare an array of values by store - replace store code with store identifier. + * + * @param array $storesData + * @return array + */ + protected function prepareStoresData(array $storesData): array + { + $storeIdsData = []; + foreach ($storesData as $storeId => $label) { + $store = $this->storeManager->getStore($storeId); + $storeIdsData[$store->getId()] = $label; + } + + return $storeIdsData; + } + + /** + * Update attribute via save product attribute controller. + * + * @param string $attributeCode + * @param array $postData + * @return void + */ + protected function updateAttributeUsingData(string $attributeCode, array $postData): void + { + $attributeId = $postData['attribute_id'] ?? $this->productAttributeRepository->get($attributeCode)->getId(); + $this->dispatchAttributeSave($postData, (int)$attributeId); + } + + /** + * Replace the store code with an identifier in the array of option values + * + * @param array $optionsArray + * @return array + */ + protected function replaceStoreCodeWithId(array $optionsArray): array + { + foreach ($optionsArray as $key => $option) { + $optionsArray[$key]['value'] = $this->prepareStoresData($option['value']); + } + + return $optionsArray; + } + + /** + * Prepare an array of attribute option values that will be saved. + * + * @param string $attributeCode + * @param array $optionsArray + * @return array + */ + protected function prepareStoreOptionsArray(string $attributeCode, array $optionsArray): array + { + $attribute = $this->productAttributeRepository->get($attributeCode); + $replacedOptionsArray = $this->replaceStoreCodeWithId($optionsArray); + $actualOptionsData = $this->getActualOptionsData($attribute->getId()); + $labeledOptionsData = []; + $optionLabelIds = []; + $i = 1; + foreach ($actualOptionsData as $optionId => $optionData) { + $optionLabelIds['option_' . $i] = $optionId; + $labeledOptionsData['option_' . $i] = $optionData; + $i++; + } + + $combineOptionsData = array_replace_recursive($labeledOptionsData, $replacedOptionsArray); + $optionsData = []; + foreach ($optionLabelIds as $optionLabel => $optionId) { + $optionsData[$optionId] = $combineOptionsData[$optionLabel]; + } + + return $optionsData; + } + + /** + * Get actual attribute options data. + * + * @param string $attributeId + * @return array + */ + protected function getActualOptionsData(string $attributeId): array + { + $attributeOptions = $this->getAttributeOptions($attributeId); + $actualOptionsData = []; + foreach ($attributeOptions as $optionId => $option) { + $actualOptionsData[$optionId] = [ + 'order' => $option->getSortOrder(), + 'value' => $this->getAttributeOptionValues($optionId), + ]; + } + + return $actualOptionsData; + } + + /** + * Prepare an array of attribute option values for sending via post parameters. + * + * @param array $optionsData + * @return array + */ + protected function prepareStoreOptionsPostData(array $optionsData): array + { + $optionsPostData = []; + foreach ($optionsData as $optionId => $option) { + $optionsPostData[$optionId]['option'] = [ + 'order' => [ + $optionId => $option['order'], + ], + 'value' => [ + $optionId => $option['value'], + ], + 'delete' => [ + $optionId => $option['delete'] ?? '', + ], + ]; + if (isset($option['default'])) { + $optionsPostData[$optionId]['default'][] = $optionId; + } + } + + return $optionsPostData; + } + + /** + * Prepare an array of attribute option values for verification after saving the attribute. + * + * @param array $optionsData + * @return array + */ + protected function prepareStoreOptionsExpectedData(array $optionsData): array + { + $optionsArray = []; + $defaultValue = ''; + + foreach ($optionsData as $optionId => $option) { + if (!empty($option['delete'])) { + continue; + } + $optionsArray[$optionId] = [ + 'order' => $option['order'], + 'value' => $option['value'], + ]; + if (isset($option['default'])) { + $defaultValue = $optionId; + } + } + + return [ + 'options_array' => $optionsArray, + 'default_value' => $defaultValue, + ]; + } + + /** + * Assert that attribute update correctly. + * + * @param string $attributeCode + * @param array $postData + * @param array $expectedData + * @return void + */ + protected function assertUpdateAttributeProcess(string $attributeCode, array $postData, array $expectedData): void + { + $this->assertSessionMessages( + $this->equalTo([(string)__('You saved the product attribute.')]), + MessageInterface::TYPE_SUCCESS + ); + $updatedAttribute = $this->productAttributeRepository->get($attributeCode); + if (isset($postData['new_attribute_set_name'])) { + $this->assertUpdateAttributeSet($updatedAttribute, $postData); + } elseif (isset($postData['options_array'])) { + $this->assertUpdateAttributeOptions($updatedAttribute, $expectedData['options_array']); + unset($expectedData['options_array']); + $this->assertUpdateAttributeData($updatedAttribute, $expectedData); + } else { + $this->assertUpdateAttributeData($updatedAttribute, $expectedData); + } + } + + /** + * Check that attribute property values match expected values. + * + * @param ProductAttributeInterface $attribute + * @param array $expectedData + * @return void + */ + protected function assertUpdateAttributeData( + ProductAttributeInterface $attribute, + array $expectedData + ): void { + foreach ($expectedData as $key => $expectedValue) { + $this->assertEquals( + $expectedValue, + $attribute->getDataUsingMethod($key), + "Invalid expected value for $key field." + ); + } + } + + /** + * Checks that appropriate error message appears. + * + * @param string $errorMessage + * @return void + */ + protected function assertErrorSessionMessages(string $errorMessage): void + { + $this->assertSessionMessages( + $this->equalTo([$this->escaper->escapeHtml($errorMessage)]), + MessageInterface::TYPE_ERROR + ); + } + + /** + * Create or update attribute using catalog/product_attribute/save action. + * + * @param array $attributeData + * @param int|null $attributeId + * @return void + */ + private function dispatchAttributeSave(array $attributeData, ?int $attributeId = null): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue($attributeData); + if ($attributeId) { + $this->getRequest()->setParam('attribute_id', $attributeId); + } + $this->dispatch('backend/catalog/product_attribute/save'); + } + + /** + * Create serialized options string. + * + * @param array $optionsArr + * @return string + */ + private function serializeOptions(array $optionsArr): string + { + $resultArr = []; + + foreach ($optionsArr as $option) { + $resultArr[] = http_build_query($option); + } + + return $this->jsonSerializer->serialize($resultArr); + } + + /** + * Set default values of attribute store labels and save. + * + * @param string $attributeCode + * @return void + */ + private function setAttributeStoreLabels(string $attributeCode): void + { + $stores = $this->storeManager->getStores(); + $storeLabels = []; + foreach ($stores as $storeId => $store) { + $storeLabels[$storeId] = $store->getName(); + } + $attribute = $this->productAttributeRepository->get($attributeCode); + $attribute->setStoreLabels($storeLabels); + $this->productAttributeRepository->save($attribute); + } + + /** + * Check that the attribute update was successful after adding it to the + * new attribute set and new attribute group. + * + * @param ProductAttributeInterface|Attribute $attribute + * @param array $postData + * @return void + */ + private function assertUpdateAttributeSet( + ProductAttributeInterface $attribute, + array $postData + ): void { + $attributeSet = $this->getAttributeSetByName->execute($postData['new_attribute_set_name']); + $this->assertNotNull( + $attributeSet, + 'The attribute set ' . $postData['new_attribute_set_name'] . 'was not created' + ); + + $attributeGroup = $this->getAttributeGroupByName->execute((int)$attributeSet->getId(), $postData['groupName']); + $this->assertNotNull( + $attributeGroup, + 'The attribute group ' . $postData['groupName'] . 'was not created' + ); + + $entityAttributeId = $this->getEntityIdByAttributeId->execute( + (int)$attributeSet->getId(), + (int)$attribute->getId(), + (int)$attributeGroup->getId() + ); + + $this->assertNotNull( + $entityAttributeId, + 'The attribute set and attribute group for the current attribute have not been updated.' + ); + } + + /** + * Check that attribute options are saved correctly. + * + * @param ProductAttributeInterface|Attribute $attribute + * @param array $expectedData + * @return void + */ + private function assertUpdateAttributeOptions( + ProductAttributeInterface $attribute, + array $expectedData + ): void { + $actualOptionsData = $this->getActualOptionsData($attribute->getId()); + + $this->assertEquals($expectedData, $actualOptionsData, 'Expected attribute options does not match.'); + } + + /** + * Get attribute options by attribute id and store id. + * + * @param string $attributeId + * @param int|null $storeId + * @return array + */ + private function getAttributeOptions(string $attributeId, ?int $storeId = null): array + { + $attributeOptionCollection = $this->optionCollectionFactory->create(); + $attributeOptionCollection->setAttributeFilter($attributeId); + $attributeOptionCollection->setStoreFilter($storeId); + + return $attributeOptionCollection->getItems(); + } + + /** + * Get attribute option values by option id. + * + * @param int $optionId + * @return array + */ + private function getAttributeOptionValues(int $optionId): array + { + $connection = $this->attributeOptionResource->getConnection(); + $select = $connection->select() + ->from( + ['main_table' => $this->attributeOptionResource->getTable('eav_attribute_option_value')], + ['store_id','value'] + ) + ->where('main_table.option_id = ?', $optionId); + + return $connection->fetchPairs($select); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/DecimalTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/DecimalTest.php new file mode 100644 index 0000000000000..0febc033592a6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/DecimalTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type price. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class DecimalTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Decimal::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_decimal_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('decimal_attribute', $postData); + $this->assertUpdateAttributeProcess('decimal_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Decimal::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_decimal_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('decimal_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\Decimal::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_decimal_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('decimal_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/MediaImageTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/MediaImageTest.php new file mode 100644 index 0000000000000..806e690dfd5b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Update/InputType/MediaImageTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type media image. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class MediaImageTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_image_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('image_attribute', $postData); + $this->assertUpdateAttributeProcess('image_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_image_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('image_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Catalog\Model\Product\Attribute\DataProvider\MediaImage::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_image_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('image_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute.php new file mode 100644 index 0000000000000..2b62f8a78252a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; +use Magento\Catalog\Setup\CategorySetup; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CategorySetup $installer */ +$installer = $objectManager->create(CategorySetup::class); +$entityType = $installer->getEntityTypeId(ProductAttributeInterface::ENTITY_TYPE_CODE); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->create(ProductAttributeRepositoryInterface::class); +/** @var Attribute $attribute */ +$attribute = $objectManager->get(AttributeFactory::class)->create(); +if (!$attribute->loadByCode($entityType, 'text_editor_attribute')->getAttributeId()) { + $attribute->setData( + [ + 'attribute_code' => 'text_editor_attribute', + 'entity_type_id' => $entityType, + 'is_global' => 1, + 'is_user_defined' => 1, + 'frontend_input' => 'textarea', + 'is_unique' => 0, + 'is_required' => 0, + 'is_searchable' => 0, + 'is_visible_in_advanced_search' => 0, + 'is_comparable' => 0, + 'is_filterable' => 0, + 'is_filterable_in_search' => 0, + 'is_used_for_promo_rules' => 0, + 'is_html_allowed_on_front' => 1, + 'is_visible_on_front' => 0, + 'used_in_product_listing' => 0, + 'used_for_sort_by' => 0, + 'frontend_label' => ['Text Editor Attribute'], + 'backend_type' => 'text', + 'is_wysiwyg_enabled' => '1', + ] + ); + $attributeRepository->save($attribute); + $installer->addAttributeToGroup( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'Default', + 'General', + $attribute->getId() + ); +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute_rollback.php new file mode 100644 index 0000000000000..09d3c1ea392ba --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_text_editor_attribute_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\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Registry; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->create(ProductAttributeRepositoryInterface::class); + +try { + $attributeRepository->deleteById('text_editor_attribute'); +} catch (NoSuchEntityException $e) { +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTest.php index cb75d3e0d4a8e..9057415cf5248 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type date. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class DateTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DropDownTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DropDownTest.php index 1a3f363832d6e..070dc850057cf 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DropDownTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DropDownTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type dropdown. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class DropDownTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/MultipleSelectTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/MultipleSelectTest.php index 1c0f5ea720f70..6f51546a5d62d 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/MultipleSelectTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/MultipleSelectTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type multiselect. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class MultipleSelectTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextAreaTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextAreaTest.php index 9c5b1a8587674..c315f61b89148 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextAreaTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextAreaTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type text_area. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class TextAreaTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextEditorTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextEditorTest.php index 807e0cfd570b2..36e95550a562a 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextEditorTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextEditorTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type text_editor. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class TextEditorTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextTest.php index 70069dcedd0e4..3a7747f59939a 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/TextTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type text. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class TextTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/YesNoTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/YesNoTest.php index 7bb26556c3fd6..28ba04465b870 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/YesNoTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/YesNoTest.php @@ -7,19 +7,20 @@ namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with yes/no input type. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class YesNoTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTest.php new file mode 100644 index 0000000000000..5df39674d05c8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type date. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class DateTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_date_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('date_attribute', $postData); + $this->assertUpdateAttributeProcess('date_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_date_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('date_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Date::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_date_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('date_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DropDownTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DropDownTest.php new file mode 100644 index 0000000000000..4b3fb2cf6fac9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DropDownTest.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type dropdown. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class DropDownTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('dropdown_attribute', $postData); + $this->assertUpdateAttributeProcess('dropdown_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('dropdown_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('dropdown_attribute', $postData, $expectedData); + } + + /** + * Test update attribute options on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DropDown::getUpdateOptionsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * + * @param array $postData + * @return void + */ + public function testUpdateOptionsOnStores(array $postData): void + { + $this->processUpdateOptionsOnStores('dropdown_attribute', $postData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/MultipleSelectTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/MultipleSelectTest.php new file mode 100644 index 0000000000000..fa8b63a2d034c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/MultipleSelectTest.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type multiselect. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class MultipleSelectTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('multiselect_attribute', $postData); + $this->assertUpdateAttributeProcess('multiselect_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('multiselect_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('multiselect_attribute', $postData, $expectedData); + } + + /** + * Test update attribute options on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\MultipleSelect::getUpdateOptionsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/multiselect_attribute.php + * + * @param array $postData + * @return void + */ + public function testUpdateOptionsOnStores(array $postData): void + { + $this->processUpdateOptionsOnStores('multiselect_attribute', $postData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextAreaTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextAreaTest.php new file mode 100644 index 0000000000000..708de8dec916c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextAreaTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type text_area. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class TextAreaTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('text_attribute', $postData); + $this->assertUpdateAttributeProcess('text_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('text_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextArea::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('text_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextEditorTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextEditorTest.php new file mode 100644 index 0000000000000..14e0f84741782 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextEditorTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type text_editor. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class TextEditorTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_text_editor_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('text_editor_attribute', $postData); + $this->assertUpdateAttributeProcess('text_editor_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_text_editor_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('text_editor_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\TextEditor::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_text_editor_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('text_editor_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextTest.php new file mode 100644 index 0000000000000..fb025e4280c96 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/TextTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type text. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class TextTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_varchar_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('varchar_attribute', $postData); + $this->assertUpdateAttributeProcess('varchar_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_varchar_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('varchar_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\Text::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_varchar_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('varchar_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/YesNoTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/YesNoTest.php new file mode 100644 index 0000000000000..c2baeba182836 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/YesNoTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with yes/no input type. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class YesNoTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getUpdateProvider + * @magentoDataFixture Magento/Catalog/_files/product_boolean_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('boolean_attribute', $postData); + $this->assertUpdateAttributeProcess('boolean_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_boolean_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('boolean_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\YesNo::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_boolean_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('boolean_attribute', $postData, $expectedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/TextSwatchTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/TextSwatchTest.php index e9839266b07a0..348afff7fe9ba 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/TextSwatchTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/TextSwatchTest.php @@ -7,7 +7,7 @@ namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; use Magento\Eav\Api\Data\AttributeInterface; use Magento\Eav\Model\Entity\Attribute\Source\Table; @@ -15,13 +15,14 @@ * Test cases related to create attribute with input type text swatch. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class TextSwatchTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -35,7 +36,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/VisualSwatchTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/VisualSwatchTest.php index 56b051c8ec9c2..0ee64f0de9ca3 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/VisualSwatchTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Save/InputType/VisualSwatchTest.php @@ -7,7 +7,7 @@ namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; use Magento\Eav\Api\Data\AttributeInterface; use Magento\Eav\Model\Entity\Attribute\Source\Table; @@ -15,13 +15,14 @@ * Test cases related to create attribute with input type visual swatch. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class VisualSwatchTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -35,7 +36,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateSwatchAttributeTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateSwatchAttributeTest.php new file mode 100644 index 0000000000000..2152a9c93419c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/AbstractUpdateSwatchAttributeTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Update; + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; +use Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory as SwatchCollectionFactory; +use Magento\Swatches\Model\Swatch; +use Magento\Swatches\Model\SwatchAttributeType; + +/** + * Base update and assert swatch attribute data. + */ +abstract class AbstractUpdateSwatchAttributeTest extends AbstractUpdateAttributeTest +{ + /** @var SwatchAttributeType */ + private $swatchAttributeType; + + /** @var SwatchCollectionFactory */ + private $swatchCollectionFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->swatchAttributeType = $this->_objectManager->get(SwatchAttributeType::class); + $this->swatchCollectionFactory = $this->_objectManager->get(SwatchCollectionFactory::class); + } + + /** + * @inheritdoc + */ + protected function replaceStoreCodeWithId(array $optionsArray): array + { + $optionsArray = parent::replaceStoreCodeWithId($optionsArray); + foreach ($optionsArray as $key => $option) { + if (isset($option['swatch'])) { + $optionsArray[$key]['swatch'] = $this->prepareStoresData($option['swatch']); + } + } + + return $optionsArray; + } + + /** + * @inheritdoc + */ + protected function getActualOptionsData(string $attributeId): array + { + $actualOptionsData = parent::getActualOptionsData($attributeId); + foreach (array_keys($actualOptionsData) as $optionId) { + $actualOptionsData[$optionId]['swatch'] = $this->getAttributeOptionSwatchValues($optionId); + } + + return $actualOptionsData; + } + + /** + * @inheritdoc + */ + protected function prepareStoreOptionsPostData(array $optionsData): array + { + $optionsPostData = parent::prepareStoreOptionsPostData($optionsData); + $swatchType = $this->getSwatchType(); + $swatchOptionsPostData = []; + + foreach ($optionsData as $optionId => $option) { + $data = []; + $data['option' . $swatchType] = $optionsPostData[$optionId]['option']; + $optionSwatch = $swatchType == Swatch::SWATCH_INPUT_TYPE_VISUAL ? $option['swatch'][0] : $option['swatch']; + + $data['swatch' . $swatchType] = [ + 'value' => [ + $optionId => $optionSwatch, + ], + ]; + if (isset($optionsPostData[$optionId]['default'])) { + $data['default' . $swatchType] = $optionsPostData[$optionId]['default']; + } + $swatchOptionsPostData[] = $data; + } + + return $swatchOptionsPostData; + } + + /** + * @inheritdoc + */ + protected function prepareStoreOptionsExpectedData(array $optionsData): array + { + $optionsExpectedData = parent::prepareStoreOptionsExpectedData($optionsData); + $optionsArray = $optionsExpectedData['options_array']; + foreach (array_keys($optionsArray) as $optionId) { + $optionsArray[$optionId]['swatch'] = $optionsData[$optionId]['swatch']; + } + + return [ + 'options_array' => $optionsArray, + 'default_value' => $optionsExpectedData['default_value'], + ]; + } + + /** + * @inheritdoc + */ + protected function assertUpdateAttributeData( + ProductAttributeInterface $attribute, + array $expectedData + ): void { + $this->swatchAttributeType->isSwatchAttribute($attribute); + parent::assertUpdateAttributeData($attribute, $expectedData); + } + + /** + * Get attribute option swatch values by option id. + * + * @param int $optionId + * @return array + */ + private function getAttributeOptionSwatchValues(int $optionId): array + { + $swatchValues = []; + $collection = $this->swatchCollectionFactory->create(); + $collection->addFieldToFilter('option_id', $optionId); + + foreach ($collection as $item) { + $swatchValues[$item->getData('store_id')] = $item->getData('value'); + } + + return $swatchValues; + } + + /** + * Get swatch type. + * + * @return string + */ + abstract protected function getSwatchType(): string; +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/TextSwatchTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/TextSwatchTest.php new file mode 100644 index 0000000000000..b62671bef04a4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/TextSwatchTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Swatches\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateSwatchAttributeTest; +use Magento\Swatches\Model\Swatch; + +/** + * Test cases related to update attribute with input type text swatch. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class TextSwatchTest extends AbstractUpdateSwatchAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getUpdateProvider + * @magentoDataFixture Magento/Swatches/_files/product_text_swatch_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('text_swatch_attribute', $postData); + $this->assertUpdateAttributeProcess('text_swatch_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Swatches/_files/product_text_swatch_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('text_swatch_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Swatches/_files/product_text_swatch_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('text_swatch_attribute', $postData, $expectedData); + } + + /** + * Test update attribute options on stores. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\TextSwatch::getUpdateOptionsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Swatches/_files/product_text_swatch_attribute.php + * + * @param array $postData + * @return void + */ + public function testUpdateOptionsOnStores(array $postData): void + { + $this->processUpdateOptionsOnStores('text_swatch_attribute', $postData); + } + + /** + * @inheritdoc + */ + protected function getSwatchType(): string + { + return Swatch::SWATCH_INPUT_TYPE_TEXT; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/VisualSwatchTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/VisualSwatchTest.php new file mode 100644 index 0000000000000..b5aa58bbd3339 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Update/InputType/VisualSwatchTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Swatches\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateSwatchAttributeTest; +use Magento\Swatches\Model\Swatch; + +/** + * Test cases related to update attribute with input type visual swatch. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class VisualSwatchTest extends AbstractUpdateSwatchAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getUpdateProvider + * @magentoDataFixture Magento/Swatches/_files/product_visual_swatch_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('visual_swatch_attribute', $postData); + $this->assertUpdateAttributeProcess('visual_swatch_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Swatches/_files/product_visual_swatch_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('visual_swatch_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Swatches/_files/product_visual_swatch_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('visual_swatch_attribute', $postData, $expectedData); + } + + /** + * Test update attribute options on stores. + * + * @dataProvider \Magento\TestFramework\Swatches\Model\Attribute\DataProvider\VisualSwatch::getUpdateOptionsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Swatches/_files/product_visual_swatch_attribute.php + * + * @param array $postData + * @return void + */ + public function testUpdateOptionsOnStores(array $postData): void + { + $this->processUpdateOptionsOnStores('visual_swatch_attribute', $postData); + } + + /** + * @inheritdoc + */ + protected function getSwatchType(): string + { + return Swatch::SWATCH_INPUT_TYPE_VISUAL; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/product_visual_swatch_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/product_visual_swatch_attribute_rollback.php index 67157532bdb98..e6b23a757441d 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/_files/product_visual_swatch_attribute_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/product_visual_swatch_attribute_rollback.php @@ -11,6 +11,7 @@ use Magento\Catalog\Api\ProductAttributeRepositoryInterface; $objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ $registry = $objectManager->get(Registry::class); $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); @@ -18,7 +19,7 @@ $attributeRepository = $objectManager->create(ProductAttributeRepositoryInterface::class); try { - $attributeRepository->deleteById('text_swatch_attribute'); + $attributeRepository->deleteById('visual_swatch_attribute'); } catch (NoSuchEntityException $e) { } $registry->unregister('isSecureArea'); diff --git a/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Save/InputType/FixedProductTaxTest.php b/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Save/InputType/FixedProductTaxTest.php index 5a6065d249b51..0c9b648a6123b 100644 --- a/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Save/InputType/FixedProductTaxTest.php +++ b/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Save/InputType/FixedProductTaxTest.php @@ -7,19 +7,20 @@ namespace Magento\Weee\Controller\Adminhtml\Product\Attribute\Save\InputType; -use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\InputType\AbstractSaveAttributeTest; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; /** * Test cases related to create attribute with input type fixed product tax. * * @magentoDbIsolation enabled + * @magentoAppArea adminhtml */ class FixedProductTaxTest extends AbstractSaveAttributeTest { /** * Test create attribute and compare attribute data and input data. * - * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getAttributeDataWithCheckArray() + * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getAttributeDataWithCheckArray * * @param array $attributePostData * @param array $checkArray @@ -33,7 +34,7 @@ public function testCreateAttribute(array $attributePostData, array $checkArray) /** * Test create attribute with error. * - * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getAttributeDataWithErrorMessage() + * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getAttributeDataWithErrorMessage * * @param array $attributePostData * @param string $errorMessage diff --git a/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Update/InputType/FixedProductTaxTest.php b/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Update/InputType/FixedProductTaxTest.php new file mode 100644 index 0000000000000..ec788bde0a002 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Weee/Controller/Adminhtml/Product/Attribute/Update/InputType/FixedProductTaxTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Weee\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type fixed product tax. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class FixedProductTaxTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getUpdateProvider + * @magentoDataFixture Magento/Weee/_files/fixed_product_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('fixed_product_attribute', $postData); + $this->assertUpdateAttributeProcess('fixed_product_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Weee/_files/fixed_product_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('fixed_product_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Weee\Model\Attribute\DataProvider\FixedProductTax::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Weee/_files/fixed_product_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('fixed_product_attribute', $postData, $expectedData); + } +} From 7e54c0b5b845a10f550b3fed58c66c2b49968786 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 15:32:41 +0200 Subject: [PATCH 435/666] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Test/AdminMoveAnchoredCategoryTest.xml | 91 ++++++++++--------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index f178d55b97fca..55c20cac593ef 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -16,9 +16,6 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-76273"/> <group value="category"/> - <skip> - <issueId value="MC-30720"/> - </skip> </annotations> <before> <createData entity="SimpleSubCategory" stepKey="simpleSubCategoryOne"/> @@ -32,95 +29,101 @@ <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="simpleSubCategoryTwo" stepKey="deleteSubcategoryTwo"/> + <actionGroup ref="logout" 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="openHomePageFirst"/> <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="openHomePageSecond"/> <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> From 46c9d2371c96b3c0e7dc94b961fe48f4c8362982 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 3 Feb 2020 16:40:14 +0200 Subject: [PATCH 436/666] MC-30166: [FT] [MFTF] [2.4] Fix flaky test UpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest (MC-6504) --- ...AdvancedPricingAddTierPriceActionGroup.xml | 34 ++++ ...mCloseAdvancedPricingDialogActionGroup.xml | 19 ++ ...rmDoneAdvancedPricingDialogActionGroup.xml | 19 ++ ...rmOpenAdvancedPricingDialogActionGroup.xml | 20 ++ ...vancedPricingCheckTierPriceActionGroup.xml | 32 ++++ .../ProductSetAdvancedPricingActionGroup.xml | 2 +- .../SetProductUrlKeyByStringActionGroup.xml | 2 +- ...AdminProductFormAdvancedPricingSection.xml | 8 + ...eInStockVisibleInCategoryAndSearchTest.xml | 176 ++++++++---------- 9 files changed, 207 insertions(+), 105 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml 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/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/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/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/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/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryAndSearchTest.xml index 04110dbd73a4c..ea331bfc97db2 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="logout" 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> From 57736707881306724368fe2a9b95680189cfb9f4 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Mon, 3 Feb 2020 10:34:36 -0600 Subject: [PATCH 437/666] Changed cc_exp_year for credit card datasets --- .../Magento/Payment/Test/Repository/CreditCard.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index 7e3266cadf0a3..c922041b7bc5f 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -10,7 +10,7 @@ <dataset name="visa_default"> <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">2042</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -18,28 +18,28 @@ <field name="cc_type" xsi:type="string">Visa</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">2042</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="visa_alt"> <field name="cc_number" xsi:type="string">4012888888881881</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2021</field> + <field name="cc_exp_year" xsi:type="string">2042</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="amex_default"> <field name="cc_number" xsi:type="string">378282246310005</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2021</field> + <field name="cc_exp_year" xsi:type="string">2042</field> <field name="cc_cid" xsi:type="string">1234</field> </dataset> <dataset name="visa_direct"> <field name="cc_number" xsi:type="string">4617747819866651</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">2042</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -54,14 +54,14 @@ <dataset name="visa_cvv_mismatch"> <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">2042</field> <field name="cc_cid" xsi:type="string">306</field> </dataset> <dataset name="mastercard_default"> <field name="cc_number" xsi:type="string">5555555555554444</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">2042</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> </repository> From 1f6569a107f9e1b9e4133036cd2ba40937894f79 Mon Sep 17 00:00:00 2001 From: rishatiwari <rishatiwari@outlook.com> Date: Sun, 2 Feb 2020 13:47:33 +0530 Subject: [PATCH 438/666] doc url updated --- phpserver/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpserver/README.md b/phpserver/README.md index e68856fc747fd..a7466557310ac 100644 --- a/phpserver/README.md +++ b/phpserver/README.md @@ -27,7 +27,7 @@ php bin/magento setup:install --base-url=http://127.0.0.1:8082 Notes: - By default, Magento creates a random Admin URI for you. Make sure to write this value down because it's how you access the Magento Admin later. For example : ```http://127.0.0.1:8082/index.php/admin_1vpn01```. -For more informations about the installation process using the CLI, you can consult the dedicated documentation that can found in [the developer documentation](https://github.com/magento/devdocs/blob/develop/guides/v2.0/install-gde/install/cli/install-cli-install.md). +For more information about the installation process using the CLI, you can consult the dedicated documentation that can found in [the developer documentation](https://devdocs.magento.com/guides/v2.3/install-gde/install/cli/install-cli-subcommands.html). ### How to run Magento From 16da7068cdcc6077ff9ea2f58a0b20f56932e310 Mon Sep 17 00:00:00 2001 From: Alexander Lukyanov <cybergomel@gmail.com> Date: Mon, 3 Feb 2020 12:57:45 -0500 Subject: [PATCH 439/666] Update Redirect.php --- app/code/Magento/Customer/Model/Account/Redirect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index e0e5730c4281b..4e3907e71eff2 100755 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -29,7 +29,7 @@ */ class Redirect { - /** @deprecated + /** @deprecated moved into its own class * @see \Magento\Customer\Model\RedirectCookieManager * URL to redirect user on successful login or registration */ From a3f548151ff4debd5e5f61d5410751b854d5cb87 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Mon, 3 Feb 2020 12:08:43 -0600 Subject: [PATCH 440/666] Changed cc_exp_year for credit card datasets - 42 was not the answer --- .../Magento/Payment/Test/Repository/CreditCard.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index c922041b7bc5f..b2c866f9cdce1 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -10,7 +10,7 @@ <dataset name="visa_default"> <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">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -18,28 +18,28 @@ <field name="cc_type" xsi:type="string">Visa</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">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="visa_alt"> <field name="cc_number" xsi:type="string">4012888888881881</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> <dataset name="amex_default"> <field name="cc_number" xsi:type="string">378282246310005</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> - <field name="cc_exp_year" xsi:type="string">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">1234</field> </dataset> <dataset name="visa_direct"> <field name="cc_number" xsi:type="string">4617747819866651</field> <field name="cc_exp_month" xsi:type="string">01 - January</field> - <field name="cc_exp_year" xsi:type="string">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> @@ -54,14 +54,14 @@ <dataset name="visa_cvv_mismatch"> <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">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">306</field> </dataset> <dataset name="mastercard_default"> <field name="cc_number" xsi:type="string">5555555555554444</field> <field name="cc_exp_month" xsi:type="string">01 - January</field> - <field name="cc_exp_year" xsi:type="string">2042</field> + <field name="cc_exp_year" xsi:type="string">2025</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> </repository> From 5f42ddb9b8fa5addaa9a88b310d525f86158aef9 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Mon, 3 Feb 2020 13:53:35 -0600 Subject: [PATCH 441/666] Fixed unstable MFTF test --- .../Test/AddConfigurableProductToOrderFromShoppingCartTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml index 6d9f35efc7903..a15e176c943ab 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml @@ -72,6 +72,7 @@ <!-- Delete category --> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <magentoCLI command="cron:run --group=index" stepKey="runCron"/> </after> <!-- Login as customer --> From c1a8ead92f47832dbac42762cbcd47fdcf82fde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Mon, 3 Feb 2020 23:46:41 +0100 Subject: [PATCH 442/666] Move additional dependencies from private getters to constructor - Magento_PageCache --- .../PageCache/Observer/FlushAllCache.php | 53 ++++---- .../PageCache/Observer/FlushCacheByTags.php | 78 +++++------- .../Test/Unit/Observer/FlushAllCacheTest.php | 86 ++++++++----- .../Unit/Observer/FlushCacheByTagsTest.php | 118 ++++++++++-------- 4 files changed, 187 insertions(+), 148 deletions(-) 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/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); } } From 28026b0a7ae03c154ca31d92b3d39145c09efd4f Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Tue, 4 Feb 2020 09:51:01 +0200 Subject: [PATCH 443/666] MC-31041: Order API response GiftCard Code not coming in API response --- app/code/Magento/Sales/Model/Order/ProductOption.php | 1 + 1 file changed, 1 insertion(+) 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]) From bde58b9ba5cd54cd82d80df1b82b48003eb3d010 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Tue, 4 Feb 2020 10:01:51 +0200 Subject: [PATCH 444/666] Use '===' operator to check if file was written. This prevents incorrect logic when writing empty string (0 bytes). --- lib/internal/Magento/Framework/Filesystem/Driver/File.php | 2 +- lib/internal/Magento/Framework/Filesystem/Driver/Http.php | 2 +- lib/internal/Magento/Framework/Filesystem/Io/File.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 59c9775d73a0a..3251f5af1bad3 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -552,7 +552,7 @@ 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( 'The specified "%1" file couldn\'t be written. %2', diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php index f32624f4e7513..9f76bb33335d3 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/Http.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/Http.php @@ -109,7 +109,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', diff --git a/lib/internal/Magento/Framework/Filesystem/Io/File.php b/lib/internal/Magento/Framework/Filesystem/Io/File.php index 8fec7f7630257..97b121beb42c2 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/File.php @@ -479,7 +479,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(); From 711ae3620b334934210098263292dd18c8e5715b Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 10:41:54 +0200 Subject: [PATCH 445/666] MC-30281: [2.4] Fix and unskip StorefrontSortingByPriceForConfigurableProductWithCatalogRuleAppliedTest --- .../Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml | 3 ++- .../NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index e0d02a280bf6c..d20798aef4838 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -11,7 +11,8 @@ <!-- action group to create a new catalog price rule giving a catalogRule entity --> <actionGroup name="NewCatalogPriceRuleByUIActionGroup"> <annotations> - <description>Goes to the Catalog Price Rule grid. Clicks on Add. Fills in the provided Catalog Rule details.</description> + <description>DEPRECATED. Please use set of AG: AdminOpenNewCatalogPriceRuleFormPageActionGroup, AdminCatalogPriceRuleFillMainInfoActionGroup, AdminCatalogPriceRuleFillActionsActionGroup, AdminCatalogPriceRuleSaveAndApplyActionGroup + Goes to the Catalog Price Rule grid. Clicks on Add. Fills in the provided Catalog Rule details.</description> </annotations> <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml index 9d25ffa948ad1..217a7519defa7 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="NewCatalogPriceRuleByUIWithConditionIsSKUActionGroup" extends="NewCatalogPriceRuleByUIActionGroup"> <annotations> - <description>EXTENDS: newCatalogPriceRuleByUI. Add a Catalog Price Rule Condition based on the provided SKU.</description> + <description>DEPRECATED. Please use set of AG: AdminOpenNewCatalogPriceRuleFormPageActionGroup, AdminCatalogPriceRuleFillMainInfoActionGroup, AdminCatalogPriceRuleFillActionsActionGroup, AdminCatalogPriceRuleAddSkuConditionActionGroup, AdminCatalogPriceRuleSaveAndApplyActionGroup + EXTENDS: newCatalogPriceRuleByUI. Add a Catalog Price Rule Condition based on the provided SKU.</description> </annotations> <arguments> <argument name="productSku"/> From 333e8af90b2a712be9278839ea1a3c2e9bb4e8d4 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Tue, 4 Feb 2020 11:01:06 +0200 Subject: [PATCH 446/666] MC-24930: Admin: Edit product Attribute --- .../TestFramework/Eav/Model/Attribute/DataProvider/Date.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php index 3c6caddfdb95c..c4e34ef8984a8 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/Date.php @@ -91,7 +91,7 @@ public function getUpdateProviderWithErrorMessage(): array [ "{$frontendInput}_wrong_default_value" => [ 'post_data' => [ - 'default_value_date' => '2019//12//12', + 'default_value_date' => '//2019/12/12', ], 'error_message' => (string)__('The default date is invalid. Verify the date and try again.'), ], From 199afbff8651b267ba52a3536784e22cc37979f6 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Tue, 4 Feb 2020 20:49:46 +1030 Subject: [PATCH 447/666] #26622 - Change to check for both parentItemId and parentItem --- app/code/Magento/SalesRule/Model/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index addfd6107f600..f05ad1eaba7fd 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,7 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItem()) { + if ($item->getParentItemId() || $item->getParentItem()) { continue; } if (!$rule->getActions()->validate($item)) { From 90c354044003d9d870f2ab52dbf0cf07ddde44b7 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Tue, 4 Feb 2020 20:54:02 +1030 Subject: [PATCH 448/666] #26622 - Update test to check combinations of parentItemId and parentItem --- .../SalesRule/Test/Unit/Model/ValidatorTest.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index e86068946ca78..93f46bc42db5a 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -346,11 +346,14 @@ public function testInitTotalsCanApplyDiscount() 'getDiscountCalculationPrice', 'getBaseDiscountCalculationPrice', 'getCalculationPrice', - 'getParentItemId' + 'getParentItemId', + 'getParentItem' ] ); $item2 = clone $item1; - $items = [$item1, $item2]; + $item3 = clone $item1; + $item4 = clone $item1; + $items = [$item1, $item2, $item3, $item4]; $rule->expects($this->any()) ->method('getSimpleAction') @@ -368,11 +371,21 @@ public function testInitTotalsCanApplyDiscount() $validator->expects($this->at(1))->method('isValid')->with($item2)->willReturn(true); $item1->expects($this->any())->method('getParentItemId')->willReturn(false); + $item1->expects($this->any())->method('getParentItem')->willReturn(false); $item1->expects($this->never())->method('getDiscountCalculationPrice'); $item1->expects($this->never())->method('getBaseDiscountCalculationPrice'); $item2->expects($this->any())->method('getParentItemId')->willReturn(false); + $item2->expects($this->any())->method('getParentItem')->willReturn(false); $item2->expects($this->any())->method('getDiscountCalculationPrice')->willReturn(50); $item2->expects($this->once())->method('getBaseDiscountCalculationPrice')->willReturn(50); + $item3->expects($this->any())->method('getParentItemId')->willReturn(false); + $item3->expects($this->any())->method('getParentItem')->willReturn(true); + $item3->expects($this->never())->method('getDiscountCalculationPrice'); + $item3->expects($this->never())->method('getBaseDiscountCalculationPrice'); + $item4->expects($this->any())->method('getParentItemId')->willReturn(true); + $item4->expects($this->any())->method('getParentItem')->willReturn(false); + $item4->expects($this->never())->method('getDiscountCalculationPrice'); + $item4->expects($this->never())->method('getBaseDiscountCalculationPrice'); $this->utility->expects($this->once())->method('getItemQty')->willReturn(1); $this->utility->expects($this->any())->method('canProcessRule')->willReturn(true); From 4efe5a09f7c801c0599786fcfaf913bab19bb99f Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 4 Feb 2020 12:57:42 +0200 Subject: [PATCH 449/666] Xml fixes for Magento_AdvancedPricingImportExport module --- app/code/Magento/AdvancedPricingImportExport/etc/module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml index 4482ba7a0a5e8..ac7e6f860382b 100644 --- a/app/code/Magento/AdvancedPricingImportExport/etc/module.xml +++ b/app/code/Magento/AdvancedPricingImportExport/etc/module.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_AdvancedPricingImportExport" /> + <module name="Magento_AdvancedPricingImportExport"/> </config> From 0702f7d88d4251defe54389fe853c27db3737ae3 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Tue, 4 Feb 2020 15:07:26 +0200 Subject: [PATCH 450/666] MC-16249: [CLOUD] Attachment is not opened on storefront --- .../Customer/Model/CustomerRegistry.php | 2 +- .../Model/App/Response/HttpPlugin.php | 3 +- .../Model/App/Response/HttpPluginTest.php | 93 +++++++++++++------ .../Php/_files/phpstan/blacklist/common.txt | 1 + 4 files changed, 70 insertions(+), 29 deletions(-) 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/PageCache/Model/App/Response/HttpPlugin.php b/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php index bf958707dde49..7a3b9055d0d12 100644 --- a/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php +++ b/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php @@ -19,9 +19,10 @@ class HttpPlugin */ public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject) { - if ($subject instanceof \Magento\Framework\App\PageCache\NotCacheableInterface) { + if ($subject instanceof \Magento\Framework\App\PageCache\NotCacheableInterface || headers_sent()) { return; } + $subject->sendVary(); } } 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..5b5fa1f0ff12a 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 @@ -4,36 +4,75 @@ * See COPYING.txt for license details. */ -namespace Magento\PageCache\Test\Unit\Model\App\Response; - -use Magento\PageCache\Model\App\Response\HttpPlugin; - -class HttpPluginTest extends \PHPUnit\Framework\TestCase -{ - /** - * @param \Magento\Framework\App\Response\FileInterface $responseInstanceClass - * @param int $sendVaryCalled - * - * @dataProvider beforeSendResponseDataProvider - */ - public function testBeforeSendResponse($responseInstanceClass, $sendVaryCalled) +// @codingStandardsIgnoreStart +namespace Magento\PageCache\Model\App\Response { + $mockPHPFunctions = false; + + function headers_sent() { - /** @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); + global $mockPHPFunctions; + if ($mockPHPFunctions) { + return false; + } + + return call_user_func_array('\headers_sent', func_get_args()); } +} + +namespace Magento\PageCache\Test\Unit\Model\App\Response { + + use Magento\Framework\App\Response\Http; + use Magento\MediaStorage\Model\File\Storage\Response; + use Magento\PageCache\Model\App\Response\HttpPlugin; - /** - * @return array - */ - public function beforeSendResponseDataProvider() + // @codingStandardsIgnoreEnd + + class HttpPluginTest extends \PHPUnit\Framework\TestCase { - return [ - [\Magento\Framework\App\Response\Http::class, 1], - [\Magento\MediaStorage\Model\File\Storage\Response::class, 0] - ]; + /** + * @inheritdoc + */ + protected function setUp() + { + global $mockPHPFunctions; + $mockPHPFunctions = true; + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + global $mockPHPFunctions; + $mockPHPFunctions = false; + } + + /** + * @param string $responseInstanceClass + * @param int $sendVaryCalled + * @return void + * + * @dataProvider beforeSendResponseDataProvider + */ + public function testBeforeSendResponse(string $responseInstanceClass, int $sendVaryCalled): void + { + /** @var Http | \PHPUnit_Framework_MockObject_MockObject $responseMock */ + $responseMock = $this->createMock($responseInstanceClass); + $responseMock->expects($this->exactly($sendVaryCalled)) + ->method('sendVary'); + $plugin = new HttpPlugin(); + $plugin->beforeSendResponse($responseMock); + } + + /** + * @return array + */ + public function beforeSendResponseDataProvider(): array + { + return [ + [Http::class, 1], + [Response::class, 0] + ]; + } } } diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt index f54defbd57604..5066040e484cb 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt @@ -14,3 +14,4 @@ dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressRepositoryTest.ph dev/tests/api-functional/testsuite/Magento/Framework/Model/Entity/HydratorTest.php dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php +app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php From 6cd172ffcc91c63ba3ddf7ed5c037287c552d956 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 15:09:02 +0200 Subject: [PATCH 451/666] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index 55c20cac593ef..7261df8765dc5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -14,7 +14,8 @@ <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"/> </annotations> <before> @@ -41,6 +42,7 @@ <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="logout" stepKey="logoutAdminUserAfterTest"/> </after> From 9308b07b07b9903f1062aa0bb9126edc92d77b83 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Tue, 4 Feb 2020 15:22:20 +0200 Subject: [PATCH 452/666] MC-24930: Admin: Edit product Attribute --- .../Model/Attribute/DataProvider/DateTime.php | 161 ++++++++++++++++++ .../_files/product_datetime_attribute.php | 54 ++++++ .../product_datetime_attribute_rollback.php | 25 +++ .../Attribute/Save/InputType/DateTimeTest.php | 48 ++++++ .../Update/InputType/DateTimeTest.php | 68 ++++++++ 5 files changed, 356 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DateTime.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTimeTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTimeTest.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DateTime.php b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DateTime.php new file mode 100644 index 0000000000000..70a8dc670e6d3 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Eav/Model/Attribute/DataProvider/DateTime.php @@ -0,0 +1,161 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Eav\Model\Attribute\DataProvider; + +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; + +/** + * Product attribute data for attribute with input type datetime. + */ +class DateTime extends AbstractBaseAttributeData +{ + /** + * @inheritdoc + */ + public function __construct() + { + parent::__construct(); + $this->defaultAttributePostData['used_for_sort_by'] = '0'; + } + + /** + * @inheritdoc + */ + public function getAttributeData(): array + { + return array_replace_recursive( + parent::getAttributeData(), + [ + "{$this->getFrontendInput()}_with_default_value" => [ + [ + 'default_value_text' => '', + 'default_value_datetime' => '02/4/2020 6:30 AM', + ] + ] + ] + ); + } + + /** + * @inheritdoc + */ + public function getAttributeDataWithCheckArray(): array + { + return array_replace_recursive( + parent::getAttributeDataWithCheckArray(), + [ + "{$this->getFrontendInput()}_with_default_value" => [ + 1 => [ + 'default_value' => '2020-02-04 06:30:00', + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + public function getUpdateProvider(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProvider(), + [ + "{$frontendInput}_other_attribute_code" => [ + 'post_data' => [ + 'attribute_code' => 'text_attribute_update', + ], + 'expected_data' => [ + 'attribute_code' => 'datetime_attribute', + ], + ], + ] + ); + } + + /** + * @inheritdoc + */ + public function getUpdateProviderWithErrorMessage(): array + { + $frontendInput = $this->getFrontendInput(); + return array_replace_recursive( + parent::getUpdateProviderWithErrorMessage(), + [ + "{$frontendInput}_wrong_default_value" => [ + 'post_data' => [ + 'default_value_datetime' => '//02/4/2020 6:30 AM', + ], + 'error_message' => (string)__('The default date is invalid. Verify the date and try again.'), + ], + ] + ); + } + + /** + * @inheritdoc + */ + protected function getFrontendInput(): string + { + return 'datetime'; + } + + /** + * @inheritdoc + */ + protected function getUpdatePostData(): array + { + return [ + 'frontend_label' => [ + Store::DEFAULT_STORE_ID => 'Date Time Attribute Update', + ], + 'frontend_input' => 'datetime', + 'is_required' => '1', + 'is_global' => ScopedAttributeInterface::SCOPE_WEBSITE, + 'default_value_datetime' => '02/4/2020 6:30 AM', + 'is_unique' => '1', + 'is_used_in_grid' => '1', + 'is_visible_in_grid' => '1', + 'is_filterable_in_grid' => '1', + 'is_searchable' => '1', + 'search_weight' => '2', + 'is_visible_in_advanced_search' => '1', + 'is_comparable' => '1', + 'is_used_for_promo_rules' => '1', + 'is_html_allowed_on_front' => '1', + 'is_visible_on_front' => '1', + 'used_in_product_listing' => '0', + 'used_for_sort_by' => '1', + ]; + } + + /** + * @inheritdoc + */ + protected function getUpdateExpectedData(): array + { + $updatePostData = $this->getUpdatePostData(); + unset($updatePostData['default_value_datetime']); + return array_merge( + $updatePostData, + [ + 'frontend_label' => 'Date Time Attribute Update', + 'attribute_code' => 'datetime_attribute', + 'default_value' => '2020-02-04 06:30:00', + 'frontend_class' => null, + 'is_filterable' => '0', + 'is_filterable_in_search' => '0', + 'position' => '0', + 'is_user_defined' => '1', + 'backend_type' => 'datetime', + ] + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute.php new file mode 100644 index 0000000000000..c1e788861266c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; +use Magento\Catalog\Setup\CategorySetup; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CategorySetup $installer */ +$installer = $objectManager->create(CategorySetup::class); +$entityType = $installer->getEntityTypeId(ProductAttributeInterface::ENTITY_TYPE_CODE); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->create(ProductAttributeRepositoryInterface::class); +/** @var Attribute $attribute */ +$attribute = $objectManager->get(AttributeFactory::class)->create(); +if (!$attribute->loadByCode($entityType, 'datetime_attribute')->getAttributeId()) { + $attribute->setData( + [ + 'attribute_code' => 'datetime_attribute', + 'entity_type_id' => $entityType, + 'is_global' => 1, + 'is_user_defined' => 1, + 'frontend_input' => 'datetime', + 'is_unique' => 0, + 'is_required' => 0, + 'is_searchable' => 0, + 'is_visible_in_advanced_search' => 0, + 'is_comparable' => 0, + 'is_filterable' => 0, + 'is_filterable_in_search' => 0, + 'is_used_for_promo_rules' => 0, + 'is_html_allowed_on_front' => 1, + 'is_visible_on_front' => 0, + 'used_in_product_listing' => 1, + 'used_for_sort_by' => 0, + 'frontend_label' => ['Date Time Attribute'], + 'backend_type' => 'datetime', + ] + ); + $attributeRepository->save($attribute); + $installer->addAttributeToGroup( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'Default', + 'General', + $attribute->getId() + ); +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute_rollback.php new file mode 100644 index 0000000000000..51b1ea5418ca9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_datetime_attribute_rollback.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Registry; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; + +$objectManager = Bootstrap::getObjectManager(); +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->create(ProductAttributeRepositoryInterface::class); + +try { + $attributeRepository->deleteById('datetime_attribute'); +} catch (NoSuchEntityException $e) { +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTimeTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTimeTest.php new file mode 100644 index 0000000000000..e80a29877a508 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Save/InputType/DateTimeTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Save\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save\AbstractSaveAttributeTest; + +/** + * Test cases related to create attribute with input type datetime. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class DateTimeTest extends AbstractSaveAttributeTest +{ + /** + * Test create attribute and compare attribute data and input data. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DateTime::getAttributeDataWithCheckArray + * @magentoConfigFixture default/general/locale/timezone UTC + * + * @param array $attributePostData + * @param array $checkArray + * @return void + */ + public function testCreateAttribute(array $attributePostData, array $checkArray): void + { + $this->createAttributeUsingDataAndAssert($attributePostData, $checkArray); + } + + /** + * Test create attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DateTime::getAttributeDataWithErrorMessage + * + * @param array $attributePostData + * @param string $errorMessage + * @return void + */ + public function testCreateAttributeWithError(array $attributePostData, string $errorMessage): void + { + $this->createAttributeUsingDataWithErrorAndAssert($attributePostData, $errorMessage); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTimeTest.php b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTimeTest.php new file mode 100644 index 0000000000000..2a6f730baf624 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Controller/Adminhtml/Product/Attribute/Update/InputType/DateTimeTest.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Eav\Controller\Adminhtml\Product\Attribute\Update\InputType; + +use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Update\AbstractUpdateAttributeTest; + +/** + * Test cases related to update attribute with input type date. + * + * @magentoDbIsolation enabled + * @magentoAppArea adminhtml + */ +class DateTimeTest extends AbstractUpdateAttributeTest +{ + /** + * Test update attribute. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DateTime::getUpdateProvider + * @magentoConfigFixture default/general/locale/timezone UTC + * @magentoDataFixture Magento/Catalog/_files/product_datetime_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateAttribute(array $postData, array $expectedData): void + { + $this->updateAttributeUsingData('datetime_attribute', $postData); + $this->assertUpdateAttributeProcess('datetime_attribute', $postData, $expectedData); + } + + /** + * Test update attribute with error. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DateTime::getUpdateProviderWithErrorMessage + * @magentoDataFixture Magento/Catalog/_files/product_datetime_attribute.php + * + * @param array $postData + * @param string $errorMessage + * @return void + */ + public function testUpdateAttributeWithError(array $postData, string $errorMessage): void + { + $this->updateAttributeUsingData('datetime_attribute', $postData); + $this->assertErrorSessionMessages($errorMessage); + } + + /** + * Test update attribute frontend labels on stores. + * + * @dataProvider \Magento\TestFramework\Eav\Model\Attribute\DataProvider\DateTime::getUpdateFrontendLabelsProvider + * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Magento/Catalog/_files/product_datetime_attribute.php + * + * @param array $postData + * @param array $expectedData + * @return void + */ + public function testUpdateFrontendLabelOnStores(array $postData, array $expectedData): void + { + $this->processUpdateFrontendLabelOnStores('datetime_attribute', $postData, $expectedData); + } +} From 4b2ef0801bce602e2686d167b7ea153e22227b80 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 4 Feb 2020 16:13:07 +0200 Subject: [PATCH 453/666] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- ...roductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml | 2 ++ .../Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml | 1 + ...AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml index 166af767be142..00e0758f6e70b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateDropdownProductAttributeVisibleInStorefrontAdvancedSearchFormTest.xml @@ -34,6 +34,8 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> + <deleteData createDataKey="attribute" stepKey="deleteProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml index 41662e4748193..12d4f825c3764 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateNewGroupForAttributeSetTest.xml @@ -27,6 +27,7 @@ </before> <after> <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index e12bac55d8bc8..ebdc6588da2f7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -31,6 +31,7 @@ <after> <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> + <deleteData createDataKey="attribute" stepKey="deleteAddedAttribute"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> From c80d0e40729692981a9c8bc3e36dafb86301e53f Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 4 Feb 2020 16:36:18 +0200 Subject: [PATCH 454/666] MC-31023: Storefront: Create configurable product on (multiple websites/multiple storeviews) --- .../Store/ExecuteInStoreContext.php | 56 ++++ ...StoreConfigurableViewOnProductPageTest.php | 255 ++++++++++++++++++ ..._attribute_different_labels_per_stores.php | 82 ++++++ ...e_different_labels_per_stores_rollback.php | 30 +++ ...ct_different_option_labeles_per_stores.php | 92 +++++++ ...ent_option_labeles_per_stores_rollback.php | 16 ++ .../configurable_product_two_websites.php | 94 +++++++ ...igurable_product_two_websites_rollback.php | 17 ++ 8 files changed, 642 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Store/ExecuteInStoreContext.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/MultiStoreConfigurableViewOnProductPageTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Store/ExecuteInStoreContext.php b/dev/tests/integration/framework/Magento/TestFramework/Store/ExecuteInStoreContext.php new file mode 100644 index 0000000000000..eee7b81e8bd32 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Store/ExecuteInStoreContext.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Store; + +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\StoreManagerInterface; + +/** + * Execute operation in specified store + */ +class ExecuteInStoreContext +{ + /** @var StoreManagerInterface */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct(StoreManagerInterface $storeManager) + { + $this->storeManager = $storeManager; + } + + /** + * Execute callback in store context + * + * @param null|string|bool|int|StoreInterface $store + * @param callable $method + * @param array $arguments + * @return mixed + */ + public function execute($store, callable $method, ...$arguments) + { + $storeCode = $store instanceof StoreInterface + ? $store->getCode() + : $this->storeManager->getStore($store)->getCode(); + $currentStore = $this->storeManager->getStore(); + + try { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($storeCode); + } + + return $method(...array_values($arguments)); + } finally { + if ($currentStore->getCode() !== $storeCode) { + $this->storeManager->setCurrentStore($currentStore); + } + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/MultiStoreConfigurableViewOnProductPageTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/MultiStoreConfigurableViewOnProductPageTest.php new file mode 100644 index 0000000000000..c1adf0ef1d2be --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/Type/MultiStoreConfigurableViewOnProductPageTest.php @@ -0,0 +1,255 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Block\Product\View\Type; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Store\ExecuteInStoreContext; +use PHPUnit\Framework\TestCase; + +/** + * Class check configurable product options displaying per stores + * + * @magentoDbIsolation disabled + */ +class MultiStoreConfigurableViewOnProductPageTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var SerializerInterface */ + private $serializer; + + /** @var ProductResource */ + private $productResource; + + /** @var ExecuteInStoreContext */ + private $executeInStoreContext; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->serializer = $this->objectManager->get(SerializerInterface::class); + $this->productResource = $this->objectManager->get(ProductResource::class); + $this->executeInStoreContext = $this->objectManager->get(ExecuteInStoreContext::class); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores.php + * + * @dataProvider expectedLabelsDataProvider + * + * @param array $expectedStoreData + * @param array $expectedSecondStoreData + * @return void + */ + public function testMultiStoreLabelView(array $expectedStoreData, array $expectedSecondStoreData): void + { + $this->executeInStoreContext->execute('default', [$this, 'assertProductLabel'], $expectedStoreData); + $this->executeInStoreContext->execute('fixturestore', [$this, 'assertProductLabel'], $expectedSecondStoreData); + } + + /** + * @return array + */ + public function expectedLabelsDataProvider(): array + { + return [ + [ + 'options_first_store' => [ + 'simple_option_1_default_store' => [ + 'label' => 'Option 1 Default Store', + ], + 'simple_option_2_default_store' => [ + 'label' => 'Option 2 Default Store', + ], + 'simple_option_3_default_store' => [ + 'label' => 'Option 3 Default Store', + ], + ], + 'options_second_store' => [ + 'simple_option_1_default_store' => [ + 'label' => 'Option 1 Second Store', + ], + 'simple_option_2_default_store' => [ + 'label' => 'Option 2 Second Store', + ], + 'simple_option_3_default_store' => [ + 'label' => 'Option 3 Second Store', + ], + ], + ], + ]; + } + + /** + * Assert configurable product labels config + * + * @param $expectedStoreData + * @return void + */ + public function assertProductLabel($expectedStoreData): void + { + $product = $this->productRepository->get('configurable', false, null, true); + $config = $this->getBlockConfig($product)['attributes'] ?? null; + $this->assertNotNull($config); + $this->assertAttributeConfig($expectedStoreData, reset($config)); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_two_websites.php + * + * @dataProvider expectedProductDataProvider + * + * @param array $expectedProducts + * @param array $expectedSecondStoreProducts + * @return void + */ + public function testMultiStoreOptionsView(array $expectedProducts, array $expectedSecondStoreProducts): void + { + $this->prepareConfigurableProduct('configurable', 'fixture_second_store'); + $this->executeInStoreContext->execute('default', [$this, 'assertProductConfig'], $expectedProducts); + $this->executeInStoreContext->execute( + 'fixture_second_store', + [$this, 'assertProductConfig'], + $expectedSecondStoreProducts + ); + } + + /** + * @return array + */ + public function expectedProductDataProvider(): array + { + return [ + [ + 'expected_store_products' => ['simple_option_1', 'simple_option_2'], + 'expected_second_store_products' => ['simple_option_2'], + ], + ]; + } + + /** + * Assert configurable product config + * + * @param $expectedProducts + * @return void + */ + public function assertProductConfig($expectedProducts): void + { + $product = $this->productRepository->get('configurable', false, null, true); + $config = $this->getBlockConfig($product)['index'] ?? null; + $this->assertNotNull($config); + $this->assertProducts($expectedProducts, $config); + } + + /** + * Prepare configurable product to test + * + * @param string $sku + * @param string $storeCode + * @return void + */ + private function prepareConfigurableProduct(string $sku, string $storeCode): void + { + $product = $this->productRepository->get($sku, false, null, true); + $productToUpdate = $product->getTypeInstance()->getUsedProductCollection($product) + ->setPageSize(1)->getFirstItem(); + $this->assertNotEmpty($productToUpdate->getData(), 'Configurable product does not have a child'); + $this->executeInStoreContext->execute($storeCode, [$this, 'setProductDisabled'], $productToUpdate); + } + + /** + * Assert product options display per stores + * + * @param array $expectedProducts + * @param array $config + * @return void + */ + private function assertProducts(array $expectedProducts, array $config): void + { + $this->assertCount(count($expectedProducts), $config); + $idsBySkus = $this->productResource->getProductsIdsBySkus($expectedProducts); + + foreach ($idsBySkus as $productId) { + $this->assertArrayHasKey($productId, $config); + } + } + + /** + * Set product status attribute to disabled + * + * @param ProductInterface $product + * @param string $storeCode + * @return void + */ + public function setProductDisabled(ProductInterface $product): void + { + $product->setStatus(Status::STATUS_DISABLED); + $this->productRepository->save($product); + } + + /** + * Get block config + * + * @param ProductInterface $product + * @return array + */ + private function getBlockConfig(ProductInterface $product): array + { + $block = $this->layout->createBlock(Configurable::class); + $block->setProduct($product); + + return $this->serializer->unserialize($block->getJsonConfig()); + } + + /** + * Assert configurable product config + * + * @param array $expectedData + * @param array $actualOptions + * @return void + */ + private function assertAttributeConfig(array $expectedData, array $actualOptions): void + { + $skus = array_keys($expectedData); + $idBySkuMap = $this->productResource->getProductsIdsBySkus($skus); + array_walk($actualOptions['options'], function (&$option) { + unset($option['id']); + }); + foreach ($expectedData as $sku => &$option) { + $option['products'] = [$idBySkuMap[$sku]]; + } + $this->assertEquals(array_values($expectedData), $actualOptions['options']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores.php new file mode 100644 index 0000000000000..0d99869d4adf9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; +use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; +use Magento\Catalog\Setup\CategorySetup; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Store\Model\Store; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../Store/_files/core_fixturestore.php'; + +$objectManager = Bootstrap::getObjectManager(); +$defaultInstalledStoreId = $storeManager->getStore('default')->getId(); +$secondStoreId = $storeManager->getStore('fixturestore')->getId(); +/** @var CategorySetup $installer */ +$installer = $objectManager->get(CategorySetup::class); +/** @var Attribute $attribute */ +$attribute = $objectManager->get(AttributeFactory::class)->create(); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class); +$entityType = $installer->getEntityTypeId(ProductAttributeInterface::ENTITY_TYPE_CODE); +if (!$attribute->loadByCode($entityType, 'different_labels_attribute')->getAttributeId()) { + $attribute->setData( + [ + 'frontend_label' => ['Different option labels dropdown attribute'], + 'entity_type_id' => $entityType, + 'frontend_input' => 'select', + 'backend_type' => 'int', + 'is_required' => '0', + 'attribute_code' => 'different_labels_attribute', + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'is_user_defined' => 1, + 'is_unique' => '0', + 'is_searchable' => '0', + 'is_comparable' => '0', + 'is_filterable' => '1', + 'is_filterable_in_search' => '0', + 'is_used_for_promo_rules' => '0', + 'is_html_allowed_on_front' => '1', + 'used_in_product_listing' => '1', + 'used_for_sort_by' => '0', + 'option' => [ + 'value' => [ + 'option_1' => [ + Store::DEFAULT_STORE_ID => 'Option 1', + $defaultInstalledStoreId => 'Option 1 Default Store', + $secondStoreId => 'Option 1 Second Store', + ], + 'option_2' => [ + Store::DEFAULT_STORE_ID => 'Option 2', + $defaultInstalledStoreId => 'Option 2 Default Store', + $secondStoreId => 'Option 2 Second Store', + ], + 'option_3' => [ + Store::DEFAULT_STORE_ID => 'Option 3', + $defaultInstalledStoreId => 'Option 3 Default Store', + $secondStoreId => 'Option 3 Second Store', + ], + ], + 'order' => [ + 'option_1' => 1, + 'option_2' => 2, + 'option_3' => 3, + ], + ], + ] + ); + $attributeRepository->save($attribute); + $installer->addAttributeToGroup( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'Default', + 'General', + $attribute->getId() + ); +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores_rollback.php new file mode 100644 index 0000000000000..f69545c831a98 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute_different_labels_per_stores_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\Framework\Exception\NoSuchEntityException; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\Registry; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var ProductAttributeRepositoryInterface $attributeRepository */ +$attributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class); + +try { + $attributeRepository->deleteById('different_labels_attribute'); +} catch (NoSuchEntityException $e) { + //already deleted +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +require __DIR__ . '/../../Store/_files/core_fixturestore_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores.php new file mode 100644 index 0000000000000..c4498c6beae4e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\ConfigurableProduct\Helper\Product\Options\Factory; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/configurable_attribute_different_labels_per_stores.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductAttributeRepositoryInterface $productAttributeRepository */ +$productAttributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class); +$attribute = $productAttributeRepository->get('different_labels_attribute'); +$options = $attribute->getOptions(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsite = $websiteRepository->get('base'); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$attributeValues = []; +$associatedProductIds = []; +$rootCategoryId = $baseWebsite->getDefaultStore()->getRootCategoryId(); +array_shift($options); + +foreach ($options as $option) { + $product = $productFactory->create(); + $product->setTypeId(ProductType::TYPE_SIMPLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsite->getId()]) + ->setName('Configurable Option ' . $option->getLabel()) + ->setSku(strtolower(str_replace(' ', '_', 'simple ' . $option->getLabel()))) + ->setPrice(150) + ->setDifferentLabelsAttribute($option->getValue()) + ->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE) + ->setStatus(Status::STATUS_ENABLED) + ->setCategoryIds([$rootCategoryId]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + $product = $productRepository->save($product); + + $attributeValues[] = [ + 'label' => 'test', + 'attribute_id' => $attribute->getId(), + 'value_index' => $option->getValue(), + ]; + $associatedProductIds[] = $product->getId(); +} +/** @var Factory $optionsFactory */ +$optionsFactory = $objectManager->get(Factory::class); +$configurableAttributesData = [ + [ + 'attribute_id' => $attribute->getId(), + 'code' => $attribute->getAttributeCode(), + 'label' => $attribute->getStoreLabel(), + 'position' => '0', + 'values' => $attributeValues, + ], +]; +$configurableOptions = $optionsFactory->create($configurableAttributesData); + +$product = $productFactory->create(); +/** @var ProductExtensionFactory $extensionAttributesFactory */ +$extensionAttributesFactory = $objectManager->get(ProductExtensionFactory::class); +$extensionConfigurableAttributes = $product->getExtensionAttributes() ?: $extensionAttributesFactory->create(); +$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions); +$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds); +$product->setExtensionAttributes($extensionConfigurableAttributes); + +$product->setTypeId(Configurable::TYPE_CODE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsite->getId()]) + ->setName('Configurable Product') + ->setSku('configurable') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setCategoryIds([$rootCategoryId]) + ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores_rollback.php new file mode 100644 index 0000000000000..c82da5f653bd8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_different_option_labeles_per_stores_rollback.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\ConfigurableProduct\Model\DeleteConfigurableProduct; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var DeleteConfigurableProduct $deleteConfigurableProduct */ +$deleteConfigurableProduct = $objectManager->get(DeleteConfigurableProduct::class); +$deleteConfigurableProduct->execute('configurable'); + +require __DIR__ . '/configurable_attribute_different_labels_per_stores_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites.php new file mode 100644 index 0000000000000..17837deb15a03 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites.php @@ -0,0 +1,94 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductExtensionFactory; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type as ProductType; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\ConfigurableProduct\Helper\Product\Options\Factory; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../Store/_files/second_website_with_two_stores.php'; +require __DIR__ . '/configurable_attribute.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductAttributeRepositoryInterface $productAttributeRepository */ +$productAttributeRepository = $objectManager->get(ProductAttributeRepositoryInterface::class); +$attribute = $productAttributeRepository->get('test_configurable'); +$options = $attribute->getOptions(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsite = $websiteRepository->get('base'); +$secondWebsite = $websiteRepository->get('test'); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +$attributeValues = []; +$associatedProductIds = []; +$rootCategoryId = $baseWebsite->getDefaultStore()->getRootCategoryId(); +array_shift($options); + +foreach ($options as $option) { + $product = $productFactory->create(); + $product->setTypeId(ProductType::TYPE_SIMPLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsite->getId(), $secondWebsite->getId()]) + ->setName('Configurable Option ' . $option->getLabel()) + ->setSku(strtolower(str_replace(' ', '_', 'simple ' . $option->getLabel()))) + ->setPrice(150) + ->setTestConfigurable($option->getValue()) + ->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE) + ->setStatus(Status::STATUS_ENABLED) + ->setCategoryIds([$rootCategoryId]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + $product = $productRepository->save($product); + + $attributeValues[] = [ + 'label' => 'test', + 'attribute_id' => $attribute->getId(), + 'value_index' => $option->getValue(), + ]; + $associatedProductIds[] = $product->getId(); +} +/** @var Factory $optionsFactory */ +$optionsFactory = $objectManager->get(Factory::class); +$configurableAttributesData = [ + [ + 'attribute_id' => $attribute->getId(), + 'code' => $attribute->getAttributeCode(), + 'label' => $attribute->getStoreLabel(), + 'position' => '0', + 'values' => $attributeValues, + ], +]; +$configurableOptions = $optionsFactory->create($configurableAttributesData); + +$product = $productFactory->create(); +/** @var ProductExtensionFactory $extensionAttributesFactory */ +$extensionAttributesFactory = $objectManager->get(ProductExtensionFactory::class); +$extensionConfigurableAttributes = $product->getExtensionAttributes() ?: $extensionAttributesFactory->create(); +$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions); +$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds); +$product->setExtensionAttributes($extensionConfigurableAttributes); + +$product->setTypeId(Configurable::TYPE_CODE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$baseWebsite->getId(), $secondWebsite->getId()]) + ->setName('Configurable Product') + ->setSku('configurable') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setCategoryIds([$rootCategoryId]) + ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites_rollback.php new file mode 100644 index 0000000000000..78e3109352693 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_two_websites_rollback.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\ConfigurableProduct\Model\DeleteConfigurableProduct; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var DeleteConfigurableProduct $deleteConfigurableProduct */ +$deleteConfigurableProduct = $objectManager->get(DeleteConfigurableProduct::class); +$deleteConfigurableProduct->execute('configurable'); + +require __DIR__ . '/configurable_attribute_rollback.php'; +require __DIR__ . '/../../Store/_files/second_website_with_two_stores_rollback.php'; From aaa8c4d3cccde10f8f65a6626be309fecba55f23 Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Tue, 4 Feb 2020 08:44:07 -0600 Subject: [PATCH 455/666] ECP-202: Deprecate Rotation Support in Magento --- app/code/Magento/Catalog/Helper/Image.php | 5 +++++ app/code/Magento/Catalog/Model/Product/Image.php | 3 +++ lib/internal/Magento/Framework/Image.php | 1 + .../Magento/Framework/Image/Adapter/AbstractAdapter.php | 1 + .../Magento/Framework/Image/Adapter/AdapterInterface.php | 1 + lib/internal/Magento/Framework/Image/Adapter/Gd2.php | 1 + lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php | 1 + 7 files changed, 13 insertions(+) diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index 3e0976936329c..5b0aa0c496ecd 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -45,6 +45,7 @@ class Image extends AbstractHelper implements ArgumentInterface * Scheduled for rotate image * * @var bool + * @deprecated unused */ protected $_scheduleRotate = false; @@ -52,6 +53,7 @@ class Image extends AbstractHelper implements ArgumentInterface * Angle * * @var int + * @deprecated unused */ protected $_angle; @@ -408,6 +410,7 @@ public function backgroundColor($colorRGB) * * @param int $angle * @return $this + * @deprecated unused */ public function rotate($angle) { @@ -617,6 +620,7 @@ protected function _getModel() * * @param int $angle * @return $this + * @deprecated unused */ protected function setAngle($angle) { @@ -628,6 +632,7 @@ protected function setAngle($angle) * Get Rotation Angle * * @return int + * @deprecated unused */ protected function getAngle() { diff --git a/app/code/Magento/Catalog/Model/Product/Image.php b/app/code/Magento/Catalog/Model/Product/Image.php index a0be36c5a327c..6c7c133223532 100644 --- a/app/code/Magento/Catalog/Model/Product/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Image.php @@ -101,6 +101,7 @@ class Image extends \Magento\Framework\Model\AbstractModel /** * @var int + * @deprecated unused */ protected $_angle; @@ -524,6 +525,7 @@ public function resize() * * @param int $angle * @return $this + * @deprecated unused */ public function rotate($angle) { @@ -539,6 +541,7 @@ public function rotate($angle) * * @param int $angle * @return $this + * @deprecated unused */ public function setAngle($angle) { diff --git a/lib/internal/Magento/Framework/Image.php b/lib/internal/Magento/Framework/Image.php index b3867c0197b79..ab88f23860704 100644 --- a/lib/internal/Magento/Framework/Image.php +++ b/lib/internal/Magento/Framework/Image.php @@ -85,6 +85,7 @@ public function save($destination = null, $newFileName = null) * @param int $angle * @access public * @return void + * @deprecated unused */ public function rotate($angle) { diff --git a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php index b06f2f9e62397..ecb10c67a7dce 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php +++ b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php @@ -204,6 +204,7 @@ abstract public function resize($width = null, $height = null); * * @param int $angle * @return void + * @deprecated unused */ abstract public function rotate($angle); diff --git a/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php b/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php index b31ed5c773495..7749664e520d0 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php +++ b/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php @@ -113,6 +113,7 @@ public function save($destination = null, $newName = null); * * @param int $angle * @return void + * @deprecated unused */ public function rotate($angle); } diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index 04d4c5386bd25..caa080c02e255 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -411,6 +411,7 @@ public function resize($frameWidth = null, $frameHeight = null) * * @param int $angle * @return void + * @deprecated unused */ public function rotate($angle) { diff --git a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php index cd49f283d33a7..418230675e356 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php +++ b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php @@ -195,6 +195,7 @@ public function resize($frameWidth = null, $frameHeight = null) * * @param int $angle * @return void + * @deprecated unused */ public function rotate($angle) { From 0dd7f9149ec349a264303daa0448a7cb92ce90aa Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" <ivan.pletnyov@transoftgroup.com> Date: Tue, 4 Feb 2020 16:52:43 +0200 Subject: [PATCH 456/666] MC-25170: Combination with different type prices --- ...CombinationWithDifferentTypePricesTest.php | 608 ++++++++++++++++++ .../_files/delete_catalog_rule_data.php | 6 + .../delete_catalog_rule_data_rollback.php | 26 + 3 files changed, 640 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php new file mode 100644 index 0000000000000..6baaf4940f94f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Pricing/Render/CombinationWithDifferentTypePricesTest.php @@ -0,0 +1,608 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Pricing\Render; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +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\Customer\Model\Group; +use Magento\Customer\Model\Session; +use Magento\Framework\Registry; +use Magento\Framework\View\Result\Page; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Assertions related to check product price rendering with combination of different price types. + * + * @magentoDbIsolation disabled + * @magentoAppArea frontend + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CombinationWithDifferentTypePricesTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Page + */ + private $page; + + /** + * @var Registry + */ + private $registry; + + /** + * @var IndexBuilder + */ + private $indexBuilder; + + /** + * @var Session + */ + private $customerSession; + + /** + * @var WebsiteRepositoryInterface + */ + private $websiteRepository; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var RuleInterfaceFactory + */ + private $catalogRuleFactory; + + /** + * @var CatalogRuleRepositoryInterface + */ + private $catalogRuleRepository; + + /** + * @var ProductTierPriceInterfaceFactory + */ + private $productTierPriceFactory; + + /** + * @var ProductTierPriceExtensionFactory + */ + private $productTierPriceExtensionFactory; + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); + $this->page = $this->objectManager->create(Page::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->indexBuilder = $this->objectManager->get(IndexBuilder::class); + $this->customerSession = $this->objectManager->get(Session::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->catalogRuleFactory = $this->objectManager->get(RuleInterfaceFactory::class); + $this->catalogRuleRepository = $this->objectManager->get(CatalogRuleRepositoryInterface::class); + $this->productTierPriceFactory = $this->objectManager->get(ProductTierPriceInterfaceFactory::class); + $this->productTierPriceExtensionFactory = $this->objectManager->get(ProductTierPriceExtensionFactory::class); + $this->productRepository->cleanCache(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + parent::tearDown(); + $this->registry->unregister('product'); + } + + /** + * Assert that product price rendered with expected special and regular prices if + * product has special price which lower than regular and tier prices. + * + * @magentoDataFixture Magento/Catalog/_files/product_special_price.php + * + * @dataProvider tierPricesForAllCustomerGroupsDataProvider + * + * @param float $specialPrice + * @param float $regularPrice + * @param array $tierPrices + * @param array|null $tierMessageConfig + * @return void + */ + public function testRenderSpecialPriceInCombinationWithTierPrice( + float $specialPrice, + float $regularPrice, + array $tierPrices, + ?array $tierMessageConfig + ): void { + $this->assertRenderedPrices($specialPrice, $regularPrice, $tierPrices, $tierMessageConfig); + } + + /** + * Data provider with tier prices which are for all customers groups. + * + * @return array + */ + public function tierPricesForAllCustomerGroupsDataProvider(): array + { + return [ + 'fixed_tier_price_with_qty_1' => [ + 5.99, + 10, + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1, 'value' => 9], + ], + null + ], + 'fixed_tier_price_with_qty_2' => [ + 5.99, + 10, + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 2, 'value' => 5], + ], + ['qty' => 2, 'price' => 5.00, 'percent' => 17], + ], + 'percent_tier_price_with_qty_2' => [ + 5.99, + 10, + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 2, 'percent_value' => 70], + ], + ['qty' => 2, 'price' => 3.00, 'percent' => 70], + ], + 'fixed_tier_price_with_qty_1_is_lower_than_special' => [ + 5, + 10, + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1, 'value' => 5], + ], + null + ], + 'percent_tier_price_with_qty_1_is_lower_than_special' => [ + 3, + 10, + [ + ['customer_group_id' => Group::NOT_LOGGED_IN_ID, 'qty' => 1, 'percent_value' => 70], + ], + null + ], + ]; + } + + /** + * Assert that product price rendered with expected special and regular prices if + * product has special price which lower than regular and tier prices and customer is logged. + * + * @magentoDataFixture Magento/Catalog/_files/product_special_price.php + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @magentoAppIsolation enabled + * + * @dataProvider tierPricesForLoggedCustomerGroupDataProvider + * + * @param float $specialPrice + * @param float $regularPrice + * @param array $tierPrices + * @param array|null $tierMessageConfig + * @return void + */ + public function testRenderSpecialPriceInCombinationWithTierPriceForLoggedInUser( + float $specialPrice, + float $regularPrice, + array $tierPrices, + ?array $tierMessageConfig + ): void { + try { + $this->customerSession->setCustomerId(1); + $this->assertRenderedPrices($specialPrice, $regularPrice, $tierPrices, $tierMessageConfig); + } finally { + $this->customerSession->setCustomerId(null); + } + } + + /** + * Data provider with tier prices which are for logged customers group. + * + * @return array + */ + public function tierPricesForLoggedCustomerGroupDataProvider(): array + { + return [ + 'fixed_tier_price_with_qty_1' => [ + 5.99, + 10, + [ + ['customer_group_id' => 1, 'qty' => 1, 'value' => 9], + ], + null + ], + 'percent_tier_price_with_qty_1' => [ + 5.99, + 10, + [ + ['customer_group_id' => 1, 'qty' => 1, 'percent_value' => 30], + ], + null + ], + ]; + } + + /** + * Assert that product price rendered with expected special and regular prices if + * product has catalog rule price with different type of prices. + * + * @magentoDataFixture Magento/Catalog/_files/product_special_price.php + * @magentoDataFixture Magento/CatalogRule/_files/delete_catalog_rule_data.php + * + * @dataProvider catalogRulesDataProvider + * + * @param float $specialPrice + * @param float $regularPrice + * @param array $catalogRules + * @param array $tierPrices + * @param array|null $tierMessageConfig + * @return void + */ + public function testRenderCatalogRulePriceInCombinationWithDifferentPriceTypes( + float $specialPrice, + float $regularPrice, + array $catalogRules, + array $tierPrices, + ?array $tierMessageConfig + ): void { + $this->createCatalogRulesForProduct($catalogRules); + $this->indexBuilder->reindexFull(); + $this->assertRenderedPrices($specialPrice, $regularPrice, $tierPrices, $tierMessageConfig); + } + + /** + * Data provider with expect special and regular price, catalog rule data and tier price. + * + * @return array + */ + public function catalogRulesDataProvider(): array + { + return [ + 'fixed_catalog_rule_price_more_than_special_price' => [ + 5.99, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 2], + ], + [], + null + ], + 'fixed_catalog_rule_price_lower_than_special_price' => [ + 2, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 8], + ], + [], + null + ], + 'fixed_catalog_rule_price_more_than_tier_price' => [ + 4, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 6], + ], + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 2, 'percent_value' => 70], + ], + ['qty' => 2, 'price' => 3.00, 'percent' => 70], + ], + 'fixed_catalog_rule_price_lower_than_tier_price' => [ + 2, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 7], + ], + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1, 'value' => 2], + ], + null + ], + 'adjust_percent_catalog_rule_price_lower_than_special_price' => [ + 4.50, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 45, RuleInterface::SIMPLE_ACTION => 'to_percent'], + ], + [], + null + ], + 'adjust_percent_catalog_rule_price_lower_than_tier_price' => [ + 3, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 30, RuleInterface::SIMPLE_ACTION => 'to_percent'], + ], + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1, 'value' => 3.50], + ], + null + ], + 'percent_catalog_rule_price_lower_than_special_price' => [ + 2, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 2, RuleInterface::SIMPLE_ACTION => 'to_fixed'], + ], + [], + null + ], + 'percent_catalog_rule_price_lower_than_tier_price' => [ + 1, + 10, + [ + [RuleInterface::DISCOUNT_AMOUNT => 1, RuleInterface::SIMPLE_ACTION => 'to_fixed'], + ], + [ + ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1, 'value' => 3], + ], + null + ], + ]; + } + + /** + * Check that price html contain all provided prices. + * + * @param string $priceHtml + * @param float $specialPrice + * @param float $regularPrice + * @return void + */ + private function checkPrices(string $priceHtml, float $specialPrice, float $regularPrice): void + { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->getSpecialPriceXpath($specialPrice), $priceHtml), + "Special price {$specialPrice} is not as expected. Rendered html: {$priceHtml}" + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->getRegularPriceLabelXpath(), $priceHtml), + "Regular price label 'Regular Price' not founded. Rendered html: {$priceHtml}" + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->getRegularPriceXpath($regularPrice), $priceHtml), + "Regular price {$regularPrice} is not as expected. Rendered html: {$priceHtml}" + ); + } + + /** + * Assert that tier price message. + * + * @param string $priceHtml + * @param array $tierMessageConfig + * @return void + */ + private function checkTierPriceMessage(string $priceHtml, array $tierMessageConfig): void + { + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath($this->getTierPriceMessageXpath($tierMessageConfig), $priceHtml), + "Tier price message not founded. Rendered html: {$priceHtml}" + ); + } + + /** + * Render price render template with product. + * + * @param ProductInterface $product + * @return string + */ + private function getPriceHtml(ProductInterface $product): string + { + $this->registerProduct($product); + $this->page->addHandle([ + 'default', + 'catalog_product_view', + ]); + $this->page->getLayout()->generateXml(); + $priceHtml = ''; + $availableChildNames = [ + 'product.info.price', + 'product.price.tier' + ]; + foreach ($this->page->getLayout()->getChildNames('product.info.main') as $childName) { + if (in_array($childName, $availableChildNames, true)) { + $priceHtml .= $this->page->getLayout()->renderElement($childName, false); + } + } + + return $priceHtml; + } + + /** + * Add product to the registry. + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('product'); + $this->registry->register('product', $product); + } + + /** + * Create provided tier prices for product. + * + * @param ProductInterface $product + * @param array $tierPrices + * @return ProductInterface + */ + private function createTierPricesForProduct(ProductInterface $product, array $tierPrices): ProductInterface + { + if (empty($tierPrices)) { + return $product; + } + + $createdTierPrices = []; + foreach ($tierPrices as $tierPrice) { + $tierPriceExtensionAttribute = $this->productTierPriceExtensionFactory->create(); + $tierPriceExtensionAttribute->setWebsiteId(0); + + if (isset($tierPrice['percent_value'])) { + $tierPriceExtensionAttribute->setPercentageValue($tierPrice['percent_value']); + unset($tierPrice['percent_value']); + } + + $createdTierPrices[] = $this->productTierPriceFactory->create( + [ + 'data' => $tierPrice + ] + )->setExtensionAttributes($tierPriceExtensionAttribute); + } + $product->setTierPrices($createdTierPrices); + + return $this->productRepository->save($product); + } + + /** + * @param float $specialPrice + * @return string + */ + private function getSpecialPriceXpath(float $specialPrice): string + { + $pathsForSearch = [ + "//div[contains(@class, 'price-box') and contains(@class, 'price-final_price')]", + "//span[contains(@class, 'special-price')]", + sprintf("//span[contains(@class, 'price') and text()='$%01.2f']", $specialPrice), + ]; + + return implode('', $pathsForSearch); + } + + /** + * @param float $regularPrice + * @return string + */ + private function getRegularPriceXpath(float $regularPrice): string + { + $pathsForSearch = [ + "//div[contains(@class, 'price-box') and contains(@class, 'price-final_price')]", + "//span[contains(@class, 'old-price')]", + "//span[contains(@class, 'price-container')]", + sprintf("//span[contains(@class, 'price') and text()='$%01.2f']", $regularPrice), + ]; + + return implode('', $pathsForSearch); + } + + /** + * @return string + */ + private function getRegularPriceLabelXpath(): string + { + $pathsForSearch = [ + "//div[contains(@class, 'price-box') and contains(@class, 'price-final_price')]", + "//span[contains(@class, 'old-price')]", + "//span[contains(@class, 'price-container')]", + "//span[text()='Regular Price']", + ]; + + return implode('', $pathsForSearch); + } + + /** + * Return tier price message xpath. Message must contain expected quantity, + * price and discount percent. + * + * @param array $expectedMessage + * @return string + */ + private function getTierPriceMessageXpath(array $expectedMessage): string + { + [$qty, $price, $percent] = array_values($expectedMessage); + $liPaths = [ + "contains(@class, 'item') and contains(text(), 'Buy {$qty} for')", + sprintf("//span[contains(@class, 'price') and text()='$%01.2f']", $price), + "//span[contains(@class, 'percent') and contains(text(), '{$percent}')]", + ]; + + return sprintf( + "//ul[contains(@class, 'prices-tier') and contains(@class, 'items')]//li[%s]", + implode(' and ', $liPaths) + ); + } + + /** + * Process test with combination of special and tier price. + * + * @param float $specialPrice + * @param float $regularPrice + * @param array $tierPrices + * @param array|null $tierMessageConfig + * @return void + */ + private function assertRenderedPrices( + float $specialPrice, + float $regularPrice, + array $tierPrices, + ?array $tierMessageConfig + ): void { + $product = $this->productRepository->get('simple', false, null, true); + $product = $this->createTierPricesForProduct($product, $tierPrices); + $priceHtml = $this->getPriceHtml($product); + $this->checkPrices($priceHtml, $specialPrice, $regularPrice); + if (null !== $tierMessageConfig) { + $this->checkTierPriceMessage($priceHtml, $tierMessageConfig); + } + } + + /** + * Create provided catalog rules. + * + * @param array $catalogRules + * @return void + */ + private function createCatalogRulesForProduct(array $catalogRules): void + { + $baseWebsite = $this->websiteRepository->get('base'); + $staticRuleData = [ + RuleInterface::IS_ACTIVE => 1, + RuleInterface::NAME => 'Test rule name.', + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + RuleInterface::SIMPLE_ACTION => 'by_fixed', + RuleInterface::STOP_RULES_PROCESSING => false, + RuleInterface::SORT_ORDER => 0, + 'sub_is_enable' => 0, + 'sub_discount_amount' => 0, + 'website_ids' => [$baseWebsite->getId()] + ]; + + foreach ($catalogRules as $catalogRule) { + $catalogRule = array_replace($staticRuleData, $catalogRule); + $catalogRule = $this->catalogRuleFactory->create(['data' => $catalogRule]); + $this->catalogRuleRepository->save($catalogRule); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data.php new file mode 100644 index 0000000000000..37121092d0ba0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data.php @@ -0,0 +1,6 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data_rollback.php new file mode 100644 index 0000000000000..77f0d1d3781f0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/delete_catalog_rule_data_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\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Api\Data\RuleInterface; +use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory; +use Magento\CatalogRule\Model\ResourceModel\Rule\Product\Price; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CollectionFactory $catalogRuleCollectionFactory */ +$catalogRuleCollectionFactory = $objectManager->get(CollectionFactory::class); +/** @var CatalogRuleRepositoryInterface $catalogRuleRepository */ +$catalogRuleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var Price $catalogRuleProductPriceResource */ +$catalogRuleProductPriceResource = $objectManager->get(Price::class); +$catalogRuleCollection = $catalogRuleCollectionFactory->create(); +/** @var RuleInterface $catalogRule */ +foreach ($catalogRuleCollection->getItems() as $catalogRule) { + $catalogRuleRepository->delete($catalogRule); +} +$catalogRuleProductPriceResource->getConnection()->delete($catalogRuleProductPriceResource->getMainTable()); From c482b31fcda339432b17a122c31f48d4bd1d4107 Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" <ivan.pletnyov@transoftgroup.com> Date: Tue, 4 Feb 2020 17:02:14 +0200 Subject: [PATCH 457/666] MC-31028: Storefront: Custom options on configurable product page --- .../View/Options/DateGroupDataProvider.php | 25 +- .../View/Options/FileGroupDataProvider.php | 13 +- .../View/Options/SelectGroupDataProvider.php | 33 +- .../View/Options/TextGroupDataProvider.php | 21 +- .../CustomOptions/DateGroupDataProvider.php | 31 ++ .../CustomOptions/FileGroupDataProvider.php | 27 ++ .../CustomOptions/SelectGroupDataProvider.php | 32 ++ .../CustomOptions/TextGroupDataProvider.php | 30 ++ .../AbstractRenderCustomOptionsTest.php | 340 ++++++++++++++++++ .../View/Options/RenderOptionsTest.php | 231 +----------- .../View/CustomOptions/RenderOptionsTest.php | 96 +++++ 11 files changed, 618 insertions(+), 261 deletions(-) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/DateGroupDataProvider.php create mode 100644 dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/FileGroupDataProvider.php create mode 100644 dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/SelectGroupDataProvider.php create mode 100644 dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/TextGroupDataProvider.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/AbstractRenderCustomOptionsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/CustomOptions/RenderOptionsTest.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/DateGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/DateGroupDataProvider.php index 7f9d5362c4f83..7e83b3f349d4d 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/DateGroupDataProvider.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/DateGroupDataProvider.php @@ -8,6 +8,7 @@ namespace Magento\TestFramework\Catalog\Block\Product\View\Options; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; use Magento\Catalog\Model\Product\Option; /** @@ -31,7 +32,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-title-1', ], [ @@ -46,7 +47,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-title-2', ], [ @@ -61,7 +62,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-title-3', ], [ @@ -76,7 +77,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-date-title-4', ], [ @@ -91,7 +92,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-and-time-title-1', ], [ @@ -106,7 +107,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-and-time-title-2', ], [ @@ -121,7 +122,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-date-and-time-title-3', ], [ @@ -136,7 +137,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-date-and-time-title-4', ], [ @@ -151,7 +152,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_TIME, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-time-title-1', ], [ @@ -166,7 +167,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-time-title-2', ], [ @@ -181,7 +182,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-time-title-3', ], [ @@ -196,7 +197,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_TIME, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-time-title-4', ], [ diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/FileGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/FileGroupDataProvider.php index c28cb770a806e..1817509539eec 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/FileGroupDataProvider.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/FileGroupDataProvider.php @@ -8,6 +8,7 @@ namespace Magento\TestFramework\Catalog\Block\Product\View\Options; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; use Magento\Catalog\Model\Product\Option; /** @@ -31,7 +32,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FILE, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-file-title-1', Option::KEY_SORT_ORDER => 1, Option::KEY_FILE_EXTENSION => 'png, jpg', @@ -51,7 +52,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FILE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-file-title-2', Option::KEY_SORT_ORDER => 1, Option::KEY_FILE_EXTENSION => 'png, jpg', @@ -71,7 +72,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FILE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-file-title-3', Option::KEY_SORT_ORDER => 1, Option::KEY_FILE_EXTENSION => 'png, jpg', @@ -91,7 +92,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FILE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-file-title-4', Option::KEY_SORT_ORDER => 1, Option::KEY_FILE_EXTENSION => 'png, jpg', @@ -111,7 +112,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FILE, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-file-title-5', Option::KEY_SORT_ORDER => 1, Option::KEY_FILE_EXTENSION => 'png, jpg', @@ -122,7 +123,7 @@ public function getData(): array 'block_with_required_class' => '<div class="field file">', 'label_for_created_option' => '<label class="label" for="options_%s_file"', 'title' => '<span>Test option file title 5</span>', - 'price' => 'data-price-amount="5"', + 'price' => 'data-price-amount="50"', 'required_element' => '/<input type="file"/', 'file_extension' => '<strong>png, jpg</strong>', 'file_width' => '/%s:.*<strong>10 px.<\/strong>/', diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/SelectGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/SelectGroupDataProvider.php index 2a13c1cd45466..ad9ffb40f5762 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/SelectGroupDataProvider.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/SelectGroupDataProvider.php @@ -8,6 +8,7 @@ namespace Magento\TestFramework\Catalog\Block\Product\View\Options; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; use Magento\Catalog\Model\Product\Option; use Magento\Catalog\Model\Product\Option\Value; @@ -35,7 +36,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option drop-down title 1 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-drop-down-title-1-value-1', ], [ @@ -58,7 +59,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option drop-down title 2 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-drop-down-title-2-value-1', ], [ @@ -81,7 +82,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option drop-down title 3 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-drop-down-title-3-value-1', ], [ @@ -104,7 +105,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option drop-down title 4 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'percent', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Value::KEY_SKU => 'test-option-drop-down-title-4-value-1', ], [ @@ -127,7 +128,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option radio-button title 1 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-radio-button-title-1-value-1', ], [ @@ -147,7 +148,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option radio-button title 2 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-radio-button-title-2-value-1', ], [ @@ -167,7 +168,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option radio-button title 3 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-radio-button-title-3-value-1', ], [ @@ -187,7 +188,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option radio-button title 4 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'percent', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Value::KEY_SKU => 'test-option-radio-button-title-4-value-1', ], [ @@ -207,7 +208,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option checkbox title 1 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-checkbox-title-1-value-1', ], [ @@ -227,7 +228,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option checkbox title 2 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-checkbox-title-2-value-1', ], [ @@ -247,7 +248,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option checkbox title 3 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-checkbox-title-3-value-1', ], [ @@ -267,7 +268,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option checkbox title 4 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'percent', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Value::KEY_SKU => 'test-option-checkbox-title-4-value-1', ], [ @@ -287,7 +288,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option multiselect title 1 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-multiselect-title-1-value-1', ], [ @@ -307,7 +308,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option multiselect title 2 value 1', Value::KEY_PRICE => 10, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-multiselect-title-2-value-1', ], [ @@ -327,7 +328,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option multiselect title 3 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'fixed', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Value::KEY_SKU => 'test-option-multiselect-title-3-value-1', ], [ @@ -347,7 +348,7 @@ public function getData(): array [ Value::KEY_TITLE => 'Test option multiselect title 4 value 1', Value::KEY_PRICE => 50, - Value::KEY_PRICE_TYPE => 'percent', + Value::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Value::KEY_SKU => 'test-option-multiselect-title-4-value-1', ], [ diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/TextGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/TextGroupDataProvider.php index 75a6da0593d73..b0d22a222dd85 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/TextGroupDataProvider.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Block/Product/View/Options/TextGroupDataProvider.php @@ -8,6 +8,7 @@ namespace Magento\TestFramework\Catalog\Block\Product\View\Options; use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; use Magento\Catalog\Model\Product\Option; /** @@ -31,7 +32,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FIELD, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-field-title-1', Option::KEY_MAX_CHARACTERS => 0, ], @@ -49,7 +50,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FIELD, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-field-title-2', Option::KEY_MAX_CHARACTERS => 0, ], @@ -67,7 +68,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FIELD, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-field-title-3', Option::KEY_MAX_CHARACTERS => 0, ], @@ -85,7 +86,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FIELD, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-field-title-4', Option::KEY_MAX_CHARACTERS => 0, ], @@ -103,7 +104,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_FIELD, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-field-title-5', Option::KEY_MAX_CHARACTERS => 99, ], @@ -122,7 +123,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_AREA, Option::KEY_IS_REQUIRE => 1, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-area-title-1', Option::KEY_MAX_CHARACTERS => 0, ], @@ -140,7 +141,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_AREA, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-area-title-2', Option::KEY_MAX_CHARACTERS => 0, ], @@ -158,7 +159,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_AREA, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-area-title-3', Option::KEY_MAX_CHARACTERS => 0, ], @@ -176,7 +177,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_AREA, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 50, - Option::KEY_PRICE_TYPE => 'percent', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_PERCENT, Option::KEY_SKU => 'test-option-area-title-4', Option::KEY_MAX_CHARACTERS => 0, ], @@ -194,7 +195,7 @@ public function getData(): array Option::KEY_TYPE => ProductCustomOptionInterface::OPTION_TYPE_AREA, Option::KEY_IS_REQUIRE => 0, Option::KEY_PRICE => 10, - Option::KEY_PRICE_TYPE => 'fixed', + Option::KEY_PRICE_TYPE => ProductPriceOptionsInterface::VALUE_FIXED, Option::KEY_SKU => 'test-option-area-title-5', Option::KEY_MAX_CHARACTERS => 99, ], diff --git a/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/DateGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/DateGroupDataProvider.php new file mode 100644 index 0000000000000..a03d3912dbd06 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/DateGroupDataProvider.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\ConfigurableProduct\Block\CustomOptions; + +use Magento\TestFramework\Catalog\Block\Product\View\Options\DateGroupDataProvider as OptionsDateGroupDataProvider; + +/** + * @inheritdoc + */ +class DateGroupDataProvider extends OptionsDateGroupDataProvider +{ + /** + * @inheritdoc + */ + public function getData(): array + { + $optionsData = parent::getData(); + unset( + $optionsData['type_date_percent_price'], + $optionsData['type_date_and_time_percent_price'], + $optionsData['type_time_percent_price'] + ); + + return $optionsData; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/FileGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/FileGroupDataProvider.php new file mode 100644 index 0000000000000..e0a22341a7ca0 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/FileGroupDataProvider.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\ConfigurableProduct\Block\CustomOptions; + +use Magento\TestFramework\Catalog\Block\Product\View\Options\FileGroupDataProvider as OptionsFileGroupDataProvider; + +/** + * @inheritdoc + */ +class FileGroupDataProvider extends OptionsFileGroupDataProvider +{ + /** + * @inheritdoc + */ + public function getData(): array + { + $optionsData = parent::getData(); + unset($optionsData['type_file_percent_price']); + + return $optionsData; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/SelectGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/SelectGroupDataProvider.php new file mode 100644 index 0000000000000..89a94f423d052 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/SelectGroupDataProvider.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\ConfigurableProduct\Block\CustomOptions; + +use Magento\TestFramework\Catalog\Block\Product\View\Options\SelectGroupDataProvider as OptionsSelectGroupDataProvider; + +/** + * @inheritdoc + */ +class SelectGroupDataProvider extends OptionsSelectGroupDataProvider +{ + /** + * @inheritdoc + */ + public function getData(): array + { + $optionsData = parent::getData(); + unset( + $optionsData['type_drop_down_value_percent_price'], + $optionsData['type_radio_button_value_percent_price'], + $optionsData['type_checkbox_value_percent_price'], + $optionsData['type_multiselect_value_percent_price'] + ); + + return $optionsData; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/TextGroupDataProvider.php b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/TextGroupDataProvider.php new file mode 100644 index 0000000000000..cf442a978b09a --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/ConfigurableProduct/Block/CustomOptions/TextGroupDataProvider.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\ConfigurableProduct\Block\CustomOptions; + +use Magento\TestFramework\Catalog\Block\Product\View\Options\TextGroupDataProvider as OptionsTextGroupDataProvider; + +/** + * @inheritdoc + */ +class TextGroupDataProvider extends OptionsTextGroupDataProvider +{ + /** + * @inheritdoc + */ + public function getData(): array + { + $optionsData = parent::getData(); + unset( + $optionsData['type_field_percent_price'], + $optionsData['type_area_percent_price'] + ); + + return $optionsData; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/AbstractRenderCustomOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/AbstractRenderCustomOptionsTest.php new file mode 100644 index 0000000000000..659cf83407a9e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/AbstractRenderCustomOptionsTest.php @@ -0,0 +1,340 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Product\View\Options; + +use Magento\Catalog\Api\Data\ProductCustomOptionInterface; +use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory; +use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterfaceFactory; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Block\Product\View\Options; +use Magento\Catalog\Model\Product\Option; +use Magento\Catalog\Model\Product\Option\Value; +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Result\Page; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Base logic for render custom options and check that option renders as expected. + */ +abstract class AbstractRenderCustomOptionsTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var ProductCustomOptionInterfaceFactory + */ + private $productCustomOptionFactory; + + /** + * @var ProductCustomOptionValuesInterfaceFactory + */ + private $productCustomOptionValuesFactory; + + /** + * @var Page + */ + private $page; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $this->productCustomOptionFactory = $this->objectManager->get(ProductCustomOptionInterfaceFactory::class); + $this->productCustomOptionValuesFactory = $this->objectManager->get( + ProductCustomOptionValuesInterfaceFactory::class + ); + $this->page = $this->objectManager->create(Page::class); + parent::setUp(); + } + + /** + * @inheritdoc + */ + protected function tearDown() + { + $this->productRepository->cleanCache(); + parent::tearDown(); + } + + /** + * Add provided options from text group to product, render options block + * and check that options rendered as expected. + * + * @param string $productSku + * @param array $optionData + * @param array $checkArray + * @return void + */ + protected function assertTextOptionRenderingOnProduct( + string $productSku, + array $optionData, + array $checkArray + ): void { + $product = $this->productRepository->get($productSku); + $product = $this->addOptionToProduct($product, $optionData); + $option = $this->findOptionByTitle($product, $optionData[Option::KEY_TITLE]); + $optionHtml = $this->getOptionHtml($product); + $this->baseOptionAsserts($option, $optionHtml, $checkArray); + + if ($optionData[Option::KEY_MAX_CHARACTERS] > 0) { + $this->assertContains($checkArray['max_characters'], $optionHtml); + } else { + $this->assertNotContains('class="character-counter', $optionHtml); + } + } + + /** + * Add provided options from file group to product, render options block + * and check that options rendered as expected. + * + * @param string $productSku + * @param array $optionData + * @param array $checkArray + * @return void + */ + protected function assertFileOptionRenderingOnProduct( + string $productSku, + array $optionData, + array $checkArray + ): void { + $product = $this->productRepository->get($productSku); + $product = $this->addOptionToProduct($product, $optionData); + $option = $this->findOptionByTitle($product, $optionData[Option::KEY_TITLE]); + $optionHtml = $this->getOptionHtml($product); + $this->baseOptionAsserts($option, $optionHtml, $checkArray); + $this->assertContains($checkArray['file_extension'], $optionHtml); + + if (isset($checkArray['file_width'])) { + $checkArray['file_width'] = sprintf($checkArray['file_width'], __('Maximum image width')); + $this->assertRegExp($checkArray['file_width'], $optionHtml); + } + + if (isset($checkArray['file_height'])) { + $checkArray['file_height'] = sprintf($checkArray['file_height'], __('Maximum image height')); + $this->assertRegExp($checkArray['file_height'], $optionHtml); + } + } + + /** + * Add provided options from select group to product, render options block + * and check that options rendered as expected. + * + * @param string $productSku + * @param array $optionData + * @param array $optionValueData + * @param array $checkArray + * @return void + */ + protected function assertSelectOptionRenderingOnProduct( + string $productSku, + array $optionData, + array $optionValueData, + array $checkArray + ): void { + $product = $this->productRepository->get($productSku); + $product = $this->addOptionToProduct($product, $optionData, $optionValueData); + $option = $this->findOptionByTitle($product, $optionData[Option::KEY_TITLE]); + $optionValues = $option->getValues(); + $optionValue = reset($optionValues); + $optionHtml = $this->getOptionHtml($product); + $this->baseOptionAsserts($option, $optionHtml, $checkArray); + + if (isset($checkArray['not_contain_arr'])) { + foreach ($checkArray['not_contain_arr'] as $notContainPattern) { + $this->assertNotRegExp($notContainPattern, $optionHtml); + } + } + + if (isset($checkArray['option_value_item'])) { + $checkArray['option_value_item'] = sprintf( + $checkArray['option_value_item'], + $optionValue->getOptionTypeId(), + $optionValueData[Value::KEY_TITLE] + ); + $this->assertRegExp($checkArray['option_value_item'], $optionHtml); + } + } + + /** + * Add provided options from date group to product, render options block + * and check that options rendered as expected. + * + * @param string $productSku + * @param array $optionData + * @param array $checkArray + * @return void + */ + protected function assertDateOptionRenderingOnProduct( + string $productSku, + array $optionData, + array $checkArray + ): void { + $product = $this->productRepository->get($productSku); + $product = $this->addOptionToProduct($product, $optionData); + $option = $this->findOptionByTitle($product, $optionData[Option::KEY_TITLE]); + $optionHtml = $this->getOptionHtml($product); + $this->baseOptionAsserts($option, $optionHtml, $checkArray); + + switch ($optionData[Option::KEY_TYPE]) { + case ProductCustomOptionInterface::OPTION_TYPE_DATE: + $this->assertContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); + break; + case ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME: + $this->assertContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); + break; + case ProductCustomOptionInterface::OPTION_TYPE_TIME: + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); + $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); + $this->assertContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); + break; + } + } + + /** + * Base asserts for rendered options. + * + * @param ProductCustomOptionInterface $option + * @param string $optionHtml + * @param array $checkArray + * @return void + */ + private function baseOptionAsserts( + ProductCustomOptionInterface $option, + string $optionHtml, + array $checkArray + ): void { + $this->assertContains($checkArray['block_with_required_class'], $optionHtml); + $this->assertContains($checkArray['title'], $optionHtml); + + if (isset($checkArray['label_for_created_option'])) { + $checkArray['label_for_created_option'] = sprintf( + $checkArray['label_for_created_option'], + $option->getOptionId() + ); + $this->assertContains($checkArray['label_for_created_option'], $optionHtml); + } + + if (isset($checkArray['price'])) { + $this->assertContains($checkArray['price'], $optionHtml); + } + + if (isset($checkArray['required_element'])) { + $this->assertRegExp($checkArray['required_element'], $optionHtml); + } + } + + /** + * Add custom option to product with data. + * + * @param ProductInterface $product + * @param array $optionData + * @param array $optionValueData + * @return ProductInterface + */ + private function addOptionToProduct( + ProductInterface $product, + array $optionData, + array $optionValueData = [] + ): ProductInterface { + $optionData[Option::KEY_PRODUCT_SKU] = $product->getSku(); + + if (!empty($optionValueData)) { + $optionValueData = $this->productCustomOptionValuesFactory->create(['data' => $optionValueData]); + $optionData['values'] = [$optionValueData]; + } + + $option = $this->productCustomOptionFactory->create(['data' => $optionData]); + $product->setOptions([$option]); + + return $this->productRepository->save($product); + } + + /** + * Render custom options block. + * + * @param ProductInterface $product + * @return string + */ + private function getOptionHtml(ProductInterface $product): string + { + $optionsBlock = $this->getOptionsBlock(); + $optionsBlock->setProduct($product); + + return $optionsBlock->toHtml(); + } + + /** + * Get options block. + * + * @return Options + */ + private function getOptionsBlock(): Options + { + $this->page->addHandle($this->getHandlesList()); + $this->page->getLayout()->generateXml(); + /** @var Template $productInfoFormOptionsBlock */ + $productInfoFormOptionsBlock = $this->page->getLayout()->getBlock('product.info.form.options'); + $optionsWrapperBlock = $productInfoFormOptionsBlock->getChildBlock('product_options_wrapper'); + + return $optionsWrapperBlock->getChildBlock('product_options'); + } + + /** + * Find and return custom option. + * + * @param ProductInterface $product + * @param string $optionTitle + * @return null|Option + */ + private function findOptionByTitle(ProductInterface $product, string $optionTitle): ?Option + { + $option = null; + foreach ($product->getOptions() as $customOption) { + if ($customOption->getTitle() === $optionTitle) { + $option = $customOption; + break; + } + } + + return $option; + } + + /** + * Return all need handles for load. + * + * @return array + */ + abstract protected function getHandlesList(): array; +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/RenderOptionsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/RenderOptionsTest.php index e83563a6ad474..da31cfc74476a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/RenderOptionsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/RenderOptionsTest.php @@ -7,74 +7,19 @@ namespace Magento\Catalog\Block\Product\View\Options; -use Magento\Catalog\Api\Data\ProductCustomOptionInterface; -use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory; -use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterfaceFactory; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Block\Product\View\Options; -use Magento\Catalog\Model\Product\Option; -use Magento\Catalog\Model\Product\Option\Value; -use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Result\Page; -use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\Helper\CacheCleaner; -use Magento\TestFramework\ObjectManager; -use PHPUnit\Framework\TestCase; - /** - * Assert that product custom options render as expected. + * Test cases related to check that simple product custom option renders as expected. * * @magentoDbIsolation disabled * @magentoAppArea frontend */ -class RenderOptionsTest extends TestCase +class RenderOptionsTest extends AbstractRenderCustomOptionsTest { - /** - * @var ObjectManager - */ - private $objectManager; - - /** - * @var ProductRepositoryInterface - */ - private $productRepository; - - /** - * @var ProductCustomOptionInterfaceFactory - */ - private $productCustomOptionFactory; - - /** - * @var ProductCustomOptionValuesInterfaceFactory - */ - private $productCustomOptionValuesFactory; - - /** - * @var Page - */ - private $page; - - /** - * @inheritdoc - */ - protected function setUp() - { - CacheCleaner::cleanAll(); - $this->objectManager = Bootstrap::getObjectManager(); - $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); - $this->productCustomOptionFactory = $this->objectManager->get(ProductCustomOptionInterfaceFactory::class); - $this->productCustomOptionValuesFactory = $this->objectManager->get( - ProductCustomOptionValuesInterfaceFactory::class - ); - $this->page = $this->objectManager->create(Page::class); - parent::setUp(); - } - /** * Check that options from text group(field, area) render as expected. * * @magentoDataFixture Magento/Catalog/_files/product_without_options_with_stock_data.php - * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\TextGroupDataProvider::getData() + * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\TextGroupDataProvider::getData * * @param array $optionData * @param array $checkArray @@ -82,22 +27,14 @@ protected function setUp() */ public function testRenderCustomOptionsFromTextGroup(array $optionData, array $checkArray): void { - $option = $this->addOptionToProduct($optionData); - $optionHtml = $this->getOptionHtml(); - $this->baseOptionAsserts($option, $optionHtml, $checkArray); - - if ($optionData[Option::KEY_MAX_CHARACTERS] > 0) { - $this->assertContains($checkArray['max_characters'], $optionHtml); - } else { - $this->assertNotContains('class="character-counter', $optionHtml); - } + $this->assertTextOptionRenderingOnProduct('simple', $optionData, $checkArray); } /** * Check that options from file group(file) render as expected. * * @magentoDataFixture Magento/Catalog/_files/product_without_options_with_stock_data.php - * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\FileGroupDataProvider::getData() + * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\FileGroupDataProvider::getData * * @param array $optionData * @param array $checkArray @@ -105,27 +42,14 @@ public function testRenderCustomOptionsFromTextGroup(array $optionData, array $c */ public function testRenderCustomOptionsFromFileGroup(array $optionData, array $checkArray): void { - $option = $this->addOptionToProduct($optionData); - $optionHtml = $this->getOptionHtml(); - $this->baseOptionAsserts($option, $optionHtml, $checkArray); - $this->assertContains($checkArray['file_extension'], $optionHtml); - - if (isset($checkArray['file_width'])) { - $checkArray['file_width'] = sprintf($checkArray['file_width'], __('Maximum image width')); - $this->assertRegExp($checkArray['file_width'], $optionHtml); - } - - if (isset($checkArray['file_height'])) { - $checkArray['file_height'] = sprintf($checkArray['file_height'], __('Maximum image height')); - $this->assertRegExp($checkArray['file_height'], $optionHtml); - } + $this->assertFileOptionRenderingOnProduct('simple', $optionData, $checkArray); } /** * Check that options from select group(drop-down, radio buttons, checkbox, multiple select) render as expected. * * @magentoDataFixture Magento/Catalog/_files/product_without_options_with_stock_data.php - * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\SelectGroupDataProvider::getData() + * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\SelectGroupDataProvider::getData * * @param array $optionData * @param array $optionValueData @@ -137,33 +61,14 @@ public function testRenderCustomOptionsFromSelectGroup( array $optionValueData, array $checkArray ): void { - $option = $this->addOptionToProduct($optionData, $optionValueData); - $optionValues = $option->getValues(); - $optionValue = reset($optionValues); - $optionHtml = $this->getOptionHtml(); - $this->baseOptionAsserts($option, $optionHtml, $checkArray); - - if (isset($checkArray['not_contain_arr'])) { - foreach ($checkArray['not_contain_arr'] as $notContainPattern) { - $this->assertNotRegExp($notContainPattern, $optionHtml); - } - } - - if (isset($checkArray['option_value_item'])) { - $checkArray['option_value_item'] = sprintf( - $checkArray['option_value_item'], - $optionValue->getOptionTypeId(), - $optionValueData[Value::KEY_TITLE] - ); - $this->assertRegExp($checkArray['option_value_item'], $optionHtml); - } + $this->assertSelectOptionRenderingOnProduct('simple', $optionData, $optionValueData, $checkArray); } /** * Check that options from date group(date, date & time, time) render as expected. * * @magentoDataFixture Magento/Catalog/_files/product_without_options_with_stock_data.php - * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\DateGroupDataProvider::getData() + * @dataProvider \Magento\TestFramework\Catalog\Block\Product\View\Options\DateGroupDataProvider::getData * * @param array $optionData * @param array $checkArray @@ -171,125 +76,17 @@ public function testRenderCustomOptionsFromSelectGroup( */ public function testRenderCustomOptionsFromDateGroup(array $optionData, array $checkArray): void { - $option = $this->addOptionToProduct($optionData); - $optionHtml = $this->getOptionHtml(); - $this->baseOptionAsserts($option, $optionHtml, $checkArray); - - switch ($optionData[Option::KEY_TYPE]) { - case ProductCustomOptionInterface::OPTION_TYPE_DATE: - $this->assertContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); - break; - case ProductCustomOptionInterface::OPTION_TYPE_DATE_TIME: - $this->assertContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); - break; - case ProductCustomOptionInterface::OPTION_TYPE_TIME: - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][month]\"", $optionHtml); - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][day]\"", $optionHtml); - $this->assertNotContains("<select name=\"options[{$option->getOptionId()}][year]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][hour]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][minute]\"", $optionHtml); - $this->assertContains("<select name=\"options[{$option->getOptionId()}][day_part]\"", $optionHtml); - break; - } + $this->assertDateOptionRenderingOnProduct('simple', $optionData, $checkArray); } /** - * Base asserts for rendered options. - * - * @param ProductCustomOptionInterface $option - * @param string $optionHtml - * @param array $checkArray - * @return void - */ - private function baseOptionAsserts( - ProductCustomOptionInterface $option, - string $optionHtml, - array $checkArray - ): void { - $this->assertContains($checkArray['block_with_required_class'], $optionHtml); - $this->assertContains($checkArray['title'], $optionHtml); - - if (isset($checkArray['label_for_created_option'])) { - $checkArray['label_for_created_option'] = sprintf( - $checkArray['label_for_created_option'], - $option->getOptionId() - ); - $this->assertContains($checkArray['label_for_created_option'], $optionHtml); - } - - if (isset($checkArray['price'])) { - $this->assertContains($checkArray['price'], $optionHtml); - } - - if (isset($checkArray['required_element'])) { - $this->assertRegExp($checkArray['required_element'], $optionHtml); - } - } - - /** - * Add custom option to product with data. - * - * @param array $optionData - * @param array $optionValueData - * @return ProductCustomOptionInterface - */ - private function addOptionToProduct(array $optionData, array $optionValueData = []): ProductCustomOptionInterface - { - $product = $this->productRepository->get('simple'); - $optionData[Option::KEY_PRODUCT_SKU] = $product->getSku(); - - if (!empty($optionValueData)) { - $optionValueData = $this->productCustomOptionValuesFactory->create(['data' => $optionValueData]); - $optionData['values'] = [$optionValueData]; - } - - $option = $this->productCustomOptionFactory->create(['data' => $optionData]); - $product->setOptions([$option]); - $createdOptions = $this->productRepository->save($product)->getOptions(); - - return reset($createdOptions); - } - - /** - * Render custom options block. - * - * @return string - */ - private function getOptionHtml(): string - { - $product = $this->productRepository->get('simple'); - $optionsBlock = $this->getOptionsBlock(); - $optionsBlock->setProduct($product); - - return $optionsBlock->toHtml(); - } - - /** - * Get options block. - * - * @return Options + * @inheritdoc */ - private function getOptionsBlock(): Options + protected function getHandlesList(): array { - $this->page->addHandle([ + return [ 'default', 'catalog_product_view', - ]); - $this->page->getLayout()->generateXml(); - /** @var Template $productInfoFormOptionsBlock */ - $productInfoFormOptionsBlock = $this->page->getLayout()->getBlock('product.info.form.options'); - $optionsWrapperBlock = $productInfoFormOptionsBlock->getChildBlock('product_options_wrapper'); - - return $optionsWrapperBlock->getChildBlock('product_options'); + ]; } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/CustomOptions/RenderOptionsTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/CustomOptions/RenderOptionsTest.php new file mode 100644 index 0000000000000..55f8b91f07093 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/View/CustomOptions/RenderOptionsTest.php @@ -0,0 +1,96 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\ConfigurableProduct\Block\Product\View\CustomOptions; + +use Magento\Catalog\Block\Product\View\Options\AbstractRenderCustomOptionsTest; + +/** + * Test cases related to check that configurable product custom option renders as expected. + * + * @magentoDbIsolation disabled + * @magentoAppArea frontend + */ +class RenderOptionsTest extends AbstractRenderCustomOptionsTest +{ + /** + * Check that options from text group(field, area) render on configurable product as expected. + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_child_products.php + * @dataProvider \Magento\TestFramework\ConfigurableProduct\Block\CustomOptions\TextGroupDataProvider::getData + * + * @param array $optionData + * @param array $checkArray + * @return void + */ + public function testRenderCustomOptionsFromTextGroup(array $optionData, array $checkArray): void + { + $this->assertTextOptionRenderingOnProduct('Configurable product', $optionData, $checkArray); + } + + /** + * Check that options from file group(file) render on configurable product as expected. + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_child_products.php + * @dataProvider \Magento\TestFramework\ConfigurableProduct\Block\CustomOptions\FileGroupDataProvider::getData + * + * @param array $optionData + * @param array $checkArray + * @return void + */ + public function testRenderCustomOptionsFromFileGroup(array $optionData, array $checkArray): void + { + $this->assertFileOptionRenderingOnProduct('Configurable product', $optionData, $checkArray); + } + + /** + * Check that options from select group(drop-down, radio buttons, checkbox, multiple select) render + * on configurable product as expected. + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_child_products.php + * @dataProvider \Magento\TestFramework\ConfigurableProduct\Block\CustomOptions\SelectGroupDataProvider::getData + * + * @param array $optionData + * @param array $optionValueData + * @param array $checkArray + * @return void + */ + public function testRenderCustomOptionsFromSelectGroup( + array $optionData, + array $optionValueData, + array $checkArray + ): void { + $this->assertSelectOptionRenderingOnProduct('Configurable product', $optionData, $optionValueData, $checkArray); + } + + /** + * Check that options from date group(date, date & time, time) render on configurable product as expected. + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_child_products.php + * @dataProvider \Magento\TestFramework\ConfigurableProduct\Block\CustomOptions\DateGroupDataProvider::getData + * + * @param array $optionData + * @param array $checkArray + * @return void + */ + public function testRenderCustomOptionsFromDateGroup(array $optionData, array $checkArray): void + { + $this->assertDateOptionRenderingOnProduct('Configurable product', $optionData, $checkArray); + } + + /** + * @inheritdoc + */ + protected function getHandlesList(): array + { + return [ + 'default', + 'catalog_product_view', + 'catalog_product_view_type_configurable', + ]; + } +} From 5ebb43bb59b97f5315ae6421fe3c1b04c6affc70 Mon Sep 17 00:00:00 2001 From: Eden <quocviet312@gmail.com> Date: Tue, 4 Feb 2020 23:19:52 +0700 Subject: [PATCH 458/666] Date incorrect on pdf invoice #26675 --- .../Framework/Stdlib/DateTime/Timezone.php | 20 ++----------------- .../Test/Unit/DateTime/TimezoneTest.php | 15 +++++++------- 2 files changed, 10 insertions(+), 25 deletions(-) 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'], From 3fdeb7f64b00727a939f02612602e8b0f1f2af43 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Tue, 4 Feb 2020 20:29:55 +0300 Subject: [PATCH 459/666] fix Unit test case and add throw exception into method declaration --- .../Catalog/Api/CategoryListDeleteBySkuInterface.php | 3 ++- .../Test/Unit/Model/CategoryLinkRepositoryTest.php | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index e4fefd19d78b7..8555bad53a3ad 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -16,10 +16,11 @@ interface CategoryListDeleteBySkuInterface * Delete by skus list * * @param int $categoryId - * @param array $productSkuList + * @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/Test/Unit/Model/CategoryLinkRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php index 8543d546b6a6b..909b952078b58 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkRepositoryTest.php @@ -261,9 +261,8 @@ public function testDelete(): void public function testDeleteBySkus(): void { $categoryId = 42; - $productSku = 'testSku'; - $productId = 55; - $productPositions = [55 => 1]; + $productSkus = ['testSku', 'testSku1', 'testSku2', 'testSku3']; + $productPositions = [55 => 1, 56 => 2, 57 => 3, 58 => 4]; $categoryMock = $this->createPartialMock( Category::class, ['getProductsPosition', 'setPostedProducts', 'save', 'getId'] @@ -271,12 +270,12 @@ public function testDeleteBySkus(): void $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $this->productResourceMock->expects($this->once())->method('getProductsIdsBySkus') - ->willReturn(['testSku' => $productId]); + ->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, [$productSku])); + $this->assertTrue($this->model->deleteBySkus($categoryId, $productSkus)); } /** From 92b3468b3c0f31cb9d700ab79bd6b1cf9dd9db3f Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Tue, 4 Feb 2020 21:06:32 +0300 Subject: [PATCH 460/666] mend --- .../Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php index 8555bad53a3ad..62eba5987c35d 100644 --- a/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryListDeleteBySkuInterface.php @@ -15,7 +15,7 @@ interface CategoryListDeleteBySkuInterface /** * Delete by skus list * - * @param int $categoryId + * @param int $categoryId * @param string[] $productSkuList * @return bool * From c45e16bf0db6e8178d41e8982135c29964f904dc Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Tue, 4 Feb 2020 15:01:04 -0600 Subject: [PATCH 461/666] Fixed issue with PHP Fatal error: Cannot redeclare Magento\Customer\Model\Session::$accountConfirmation --- app/code/Magento/Customer/Model/Session.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/code/Magento/Customer/Model/Session.php b/app/code/Magento/Customer/Model/Session.php index 8fc4d9c63458f..55e31cb4555b4 100644 --- a/app/code/Magento/Customer/Model/Session.php +++ b/app/code/Magento/Customer/Model/Session.php @@ -99,11 +99,6 @@ class Session extends \Magento\Framework\Session\SessionManager */ protected $_httpContext; - /** - * @var AccountConfirmation - */ - protected $accountConfirmation; - /** * @var GroupManagementInterface */ From 96a2e17754c78e3939fcbe14f7729d7ded52e544 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Tue, 4 Feb 2020 15:19:37 -0600 Subject: [PATCH 462/666] MC-30236: Upgrade from 2.3.x CE with SD to 2.3.x EE AreaCode Exception --- setup/src/Magento/Setup/Model/Installer.php | 42 +++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 23f8a13c8bfe8..ee7d5a196127b 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,9 @@ public function installDataFixtures(array $request = []) $setup = $this->dataSetupFactory->create(); $this->checkFilePermissionsForDbUpgrade(); $this->log->log('Data install/update:'); + $this->updateCaches(false, $frontendCaches, false); $this->handleDBSchemaData($setup, 'data', $request); + $this->updateCaches(true, $frontendCaches, false); $registry->unregister('setup-mode-enabled'); } @@ -1248,23 +1259,32 @@ public function uninstall() } /** - * Enables caches after installing application + * Enable or disable caches for specific types * - * @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 + * @param bool $logStatus + * @return void */ - private function enableCaches() + private function updateCaches($isEnabled, $types = [], $logStatus = true) { /** @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); + $types = empty($types) ? $cacheManager->getAvailableTypes() : $types; + + $enabledTypes = $cacheManager->setEnabled($types, $isEnabled); + if($isEnabled){ + $cacheManager->clean($enabledTypes); + } - $this->log->log('Current status:'); - // phpcs:ignore Magento2.Functions.DiscouragedFunction - $this->log->log(print_r($cacheManager->getStatus(), true)); + if ($logStatus) { + $this->log->log('Current status:'); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $this->log->log(print_r($cacheManager->getStatus(), true)); + } } /** From a027e87a3d0393bc0639033e2e0ecf14d51f44a9 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Wed, 5 Feb 2020 01:40:08 +0200 Subject: [PATCH 463/666] Prevent endless loop when duplicating product Remove redundant backward compatibility in constructor --- app/code/Magento/Catalog/Model/Product/Copier.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index d10bf085a4a25..91fb5213281ec 100644 --- a/app/code/Magento/Catalog/Model/Product/Copier.php +++ b/app/code/Magento/Catalog/Model/Product/Copier.php @@ -59,14 +59,14 @@ public function __construct( CopyConstructorInterface $copyConstructor, ProductFactory $productFactory, ScopeOverriddenValue $scopeOverriddenValue, - OptionRepository $optionRepository = null, - MetadataPool $metadataPool = null + OptionRepository $optionRepository, + MetadataPool $metadataPool ) { $this->productFactory = $productFactory; $this->copyConstructor = $copyConstructor; $this->scopeOverriddenValue = $scopeOverriddenValue; - $this->optionRepository = $optionRepository ?: ObjectManager::getInstance()->get(OptionRepository::class); - $this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class); + $this->optionRepository = $optionRepository; + $this->metadataPool = $metadataPool; } /** From 5f4cc5f6f81776db4419be934c1a3afd159fd38e Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 10:30:49 +1030 Subject: [PATCH 464/666] #26622 - Reduce cyclomatic complexity of initTotals function --- .../Magento/SalesRule/Model/Validator.php | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index f05ad1eaba7fd..913c77655b946 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -383,13 +383,7 @@ public function initTotals($items, Address $address) foreach ($items as $item) { //Skipping child items to avoid double calculations - if ($item->getParentItemId() || $item->getParentItem()) { - continue; - } - if (!$rule->getActions()->validate($item)) { - continue; - } - if (!$this->canApplyDiscount($item)) { + if (!$this->isValidItemForRule($item, $rule)) { continue; } $qty = $this->validatorUtility->getItemQty($item, $rule); @@ -409,6 +403,32 @@ public function initTotals($items, Address $address) return $this; } + /** + * Determine if quote item is valid for a given sales rule + * @param AbstractItem $item + * @param Rule $rule + * @return bool + */ + protected function isValidItemForRule( + AbstractItem $item, + Rule $rule + ) { + /** @var AbstractItem $item */ + if ($item->getParentItemId()) { + return false; + } + if ($item->getParentItem()) { + return false; + } + if (!$rule->getActions()->validate($item)) { + return false; + } + if (!$this->canApplyDiscount($item)) { + return false; + } + return true; + } + /** * Return item price * From 0e9c4ef9d7d541f8dba35052731f8d2d152fe4f7 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 10:31:21 +1030 Subject: [PATCH 465/666] #26622 - Update class description to fix failing static test --- app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index 93f46bc42db5a..30b198e5b9199 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\MockObject\MockObject; /** - * Class ValidatorTest + * Tests for Magento\SalesRule\Model\Validator * @@SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ValidatorTest extends \PHPUnit\Framework\TestCase From 2c961afa3170257c4bed3c26d0d57d42d5445035 Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Wed, 5 Feb 2020 11:16:57 +1030 Subject: [PATCH 466/666] #26622 - Fix code style --- app/code/Magento/SalesRule/Model/Validator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 913c77655b946..8292e9c313b66 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -405,6 +405,7 @@ public function initTotals($items, Address $address) /** * Determine if quote item is valid for a given sales rule + * * @param AbstractItem $item * @param Rule $rule * @return bool From 49e67f49655adac4e191236b764c67fccd9e3e29 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 5 Feb 2020 09:25:20 +0200 Subject: [PATCH 467/666] MC-30789: GTM is not trigged without Page Reload --- app/code/Magento/Cookie/view/frontend/web/js/notices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9c51a49187c32..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,7 +30,7 @@ define([ if ($.mage.cookies.get(this.options.cookieName)) { this.element.hide(); - $(document).trigger('ga:init'); + $(document).trigger('user:allowed:save:cookie'); } else { window.location.href = this.options.noCookiesUrl; } From 8e45388870b322fc7ea16e23e80ca58abc332599 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 5 Feb 2020 11:12:45 +0200 Subject: [PATCH 468/666] MC-29943: [FT] Test StorefrontOrderPagerDisplayedTest fails on Jenkins --- .../AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml index ebdc6588da2f7..e12bac55d8bc8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteTextFieldProductAttributeFromAttributeSetTest.xml @@ -31,7 +31,6 @@ <after> <!--Delete cteated Data --> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimplaeProduct"/> - <deleteData createDataKey="attribute" stepKey="deleteAddedAttribute"/> <actionGroup ref="logout" stepKey="logout"/> <!-- Reindex invalidated indices after product attribute has been created/deleted --> From e33df779e67f8a78a666e42867d7194b88f4c0da Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 5 Feb 2020 11:35:09 +0200 Subject: [PATCH 469/666] test commit --- .../Unit/TemplateEngine/Xhtml/ResultTest.php | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php 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..f4f81ade42f08 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -0,0 +1,151 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +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\Layout\Generator\Structure; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Template; +use Magento\Ui\TemplateEngine\Xhtml\Result; +use Magento\Framework\Serialize\Serializer\JsonHexTag; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Test for \Magento\Ui\TemplateEngine\Xhtml\Result. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ResultTest extends TestCase +{ + /** + * @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 Structure|MockObject + */ + private $structureMock; + + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var JsonHexTag|MockObject + */ + private $jsonSerializerMock; + + /** + * @var State|MockObject + */ + private $stateMock; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->templateMock = $this->getMockBuilder(Template::class) + ->setMethods(['getDocumentElement']) + ->disableOriginalConstructor() + ->getMock(); + $this->compilerMock = $this->getMockBuilder(CompilerInterface::class) + ->setMethods(['compile']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->componentMock = $this->getMockBuilder(UiComponentInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->structureMock = $this->getMockBuilder(Structure::class) + ->disableOriginalConstructor() + ->getMock(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->getMock(); + $this->jsonSerializerMock = $this->getMockBuilder(JsonHexTag::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $this->objectManagerHelper->getObject( + Result::class, + [ + 'template' => $this->templateMock, + 'compiler' => $this->compilerMock, + 'component' => $this->componentMock, + 'structure' => $this->structureMock, + 'logger' => $this->loggerMock, + 'jsonSerializer' => $this->jsonSerializerMock, + 'state' => $this->stateMock, + ] + ); + } + + /** + * To string method with exception message + * + * @return void + */ + public function testToStringWithException(): void + { + $exception = new \Exception(); + $this->templateMock->method('getDocumentElement')->willThrowException($exception); + $this->stateMock->method('getMode')->willReturn(State::MODE_DEVELOPER); + + $this->assertEquals( + '<pre><code>' . $exception->__toString() . '</code></pre>', + $this->model->__toString() + ); + } + + /** + * To string method + * + * @return void + */ + public function testToString(): void + { + $domElementMock = $this->getMockBuilder(\DOMElement::class) + ->enableOriginalConstructor() + ->setConstructorArgs(['new']) + ->getMock(); + $this->templateMock->method('getDocumentElement')->willReturn($domElementMock); + $this->compilerMock->method('compile') + ->with($domElementMock, $this->componentMock, $this->componentMock)->willReturn(true); + + $this->assertInternalType('string', $this->model->__toString()); + } +} From 427a4ad298210ed5287044cd49c51391daa0af65 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Wed, 5 Feb 2020 09:43:51 +0000 Subject: [PATCH 470/666] Update dockblocks to return null --- .../Magento/Sales/Api/Data/OrderInterface.php | 8 ------- app/code/Magento/Sales/Model/Order.php | 23 +------------------ 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index f699d24bd32cd..b45fddc7d7354 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -5,8 +5,6 @@ */ namespace Magento\Sales\Api\Data; -use Magento\Customer\Model\Customer; - /** * Order interface. * @@ -912,12 +910,6 @@ public function getCreatedAt(); */ public function setCreatedAt($createdAt); - /** - * Gets the customer from Order - * @return Customer - */ - public function getCustomer(); - /** * Gets the customer date-of-birth (DOB) for the order. * diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 1d520574f21d7..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -6,7 +6,6 @@ namespace Magento\Sales\Model; use Magento\Config\Model\Config\Source\Nooptreq; -use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Directory\Model\Currency; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -52,6 +51,7 @@ * @method bool hasCustomerNoteNotify() * @method bool hasForcedCanCreditmemo() * @method bool getIsInProcess() + * @method \Magento\Customer\Model\Customer|null getCustomer() * @method \Magento\Sales\Model\Order setSendEmail(bool $value) * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) @@ -307,11 +307,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ private $scopeConfig; - /** - * @var CustomerRepositoryInterface - */ - private $_customerRepositoryInterface; - /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -345,7 +340,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param OrderItemRepositoryInterface $itemRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param ScopeConfigInterface $scopeConfig - * @param CustomerRepositoryInterface $customerRepositoryInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -372,7 +366,6 @@ public function __construct( \Magento\Sales\Model\ResourceModel\Order\Shipment\Track\CollectionFactory $trackCollectionFactory, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $salesOrderCollectionFactory, PriceCurrencyInterface $priceCurrency, - CustomerRepositoryInterface $customerRepositoryInterface, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productListFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -410,7 +403,6 @@ public function __construct( $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: ObjectManager::getInstance() ->get(SearchCriteriaBuilder::class); $this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class); - $this->_customerRepositoryInterface = $customerRepositoryInterface; parent::__construct( $context, @@ -570,19 +562,6 @@ public function getStore() return $this->_storeManager->getStore(); } - /** - * Returns Customer - * - * @return \Magento\Customer\Api\Data\CustomerInterface - * @throws LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - public function getCustomer() - { - $customerId = $this->getData(OrderInterface::CUSTOMER_ID); - return $this->_customerRepositoryInterface->getById($customerId); - } - /** * Retrieve order cancel availability * From 834e37eff8a89477b2a557c7eaa03a36b2b1facb Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 5 Feb 2020 11:47:48 +0200 Subject: [PATCH 471/666] Adjusting the template and Integration test --- .../view/frontend/templates/form/edit.phtml | 72 +++++++++++++------ .../Customer/Controller/AccountTest.php | 23 +++--- 2 files changed, 64 insertions(+), 31 deletions(-) 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..d29f6917793b2 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'), @@ -116,13 +147,14 @@ }); </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/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index df4acf3acca91..84845545d54f3 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -509,11 +509,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 +530,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); } /** From fd3100eccc2b633a4695b90c7b449f959c713067 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 5 Feb 2020 12:16:20 +0200 Subject: [PATCH 472/666] improvements --- .../Unit/TemplateEngine/Xhtml/ResultTest.php | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php index f4f81ade42f08..47c7bae9934ae 100644 --- a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -17,6 +17,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Magento\Framework\DataObject; /** * Test for \Magento\Ui\TemplateEngine\Xhtml\Result. @@ -75,29 +76,13 @@ class ResultTest extends TestCase */ protected function setUp() { - $this->templateMock = $this->getMockBuilder(Template::class) - ->setMethods(['getDocumentElement']) - ->disableOriginalConstructor() - ->getMock(); - $this->compilerMock = $this->getMockBuilder(CompilerInterface::class) - ->setMethods(['compile']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->componentMock = $this->getMockBuilder(UiComponentInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->structureMock = $this->getMockBuilder(Structure::class) - ->disableOriginalConstructor() - ->getMock(); - $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->stateMock = $this->getMockBuilder(State::class) - ->disableOriginalConstructor() - ->getMock(); - $this->jsonSerializerMock = $this->getMockBuilder(JsonHexTag::class) - ->disableOriginalConstructor() - ->getMock(); + $this->templateMock = $this->createMock(Template::class); + $this->compilerMock = $this->createMock(CompilerInterface::class); + $this->componentMock = $this->createMock(\Magento\Ui\Component\Listing::class); + $this->structureMock = $this->createMock(Structure::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->stateMock = $this->createMock(State::class); + $this->jsonSerializerMock = $this->createMock(JsonHexTag::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( @@ -122,7 +107,10 @@ protected function setUp() public function testToStringWithException(): void { $exception = new \Exception(); - $this->templateMock->method('getDocumentElement')->willThrowException($exception); + + $this->templateMock->expects($this->once()) + ->method('getDocumentElement') + ->willThrowException($exception); $this->stateMock->method('getMode')->willReturn(State::MODE_DEVELOPER); $this->assertEquals( @@ -139,13 +127,20 @@ public function testToStringWithException(): void public function testToString(): void { $domElementMock = $this->getMockBuilder(\DOMElement::class) - ->enableOriginalConstructor() - ->setConstructorArgs(['new']) + ->setConstructorArgs(['a']) ->getMock(); - $this->templateMock->method('getDocumentElement')->willReturn($domElementMock); - $this->compilerMock->method('compile') - ->with($domElementMock, $this->componentMock, $this->componentMock)->willReturn(true); - $this->assertInternalType('string', $this->model->__toString()); + $this->templateMock->expects($this->exactly(2)) + ->method('getDocumentElement') + ->willReturn($domElementMock); + $this->compilerMock->expects($this->once()) + ->method('compile') + ->with( + $this->isInstanceOf('\DOMElement'), + $this->componentMock, + $this->componentMock + ); + + $this->assertEquals('string', $this->model->__toString()); } } From 013d0ba3e08935319ab9e6af80b4e964a6b47d47 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 5 Feb 2020 12:22:51 +0200 Subject: [PATCH 473/666] Fixing additionally static tests --- .../Magento/Customer/view/frontend/templates/form/edit.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d29f6917793b2..89b86f8af8e55 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml @@ -7,7 +7,7 @@ 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" @@ -140,7 +140,7 @@ use Magento\Customer\Block\Widget\Name; } }, ignore: ':hidden:not(' + ignore + ')' - <?php else : ?> + <?php else: ?> ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' <?php endif ?> }); From 2449839962b1ee6a5e6f24e75c358b05942e9892 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 5 Feb 2020 13:13:58 +0200 Subject: [PATCH 474/666] Unit test for \Magento\Captcha\Observer\CheckUserForgotPasswordBackendObserver --- ...kUserForgotPasswordBackendObserverTest.php | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php 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..346814aca2084 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php @@ -0,0 +1,188 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Captcha\Test\Unit\Observer; + +use Magento\Captcha\Helper\Data as DataHelper; +use Magento\Captcha\Model\CaptchaInterface; +use Magento\Captcha\Observer\CaptchaStringResolver; +use Magento\Captcha\Observer\CheckUserForgotPasswordBackendObserver; +use Magento\Framework\App\Action\Action; +use Magento\Framework\App\ActionFlag; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\App\Response\Http as HttpResponse; +use Magento\Framework\Event\Observer; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Session\SessionManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Captcha\Observer\CheckUserForgotPasswordBackendObserver + */ +class CheckUserForgotPasswordBackendObserverTest extends TestCase +{ + /** + * @var MockObject|DataHelper + */ + private $helperMock; + + /** + * @var MockObject|CaptchaStringResolver + */ + private $captchaStringResolverMock; + + /** + * @var MockObject|SessionManagerInterface + */ + private $sessionMock; + + /** + * @var MockObject|ActionFlag + */ + private $actionFlagMock; + + /** + * @var MockObject|ManagerInterface + */ + private $messageManagerMock; + + /** + * @var CheckUserForgotPasswordBackendObserver + */ + private $observer; + + /** + * @var MockObject + */ + private $captchaMock; + + /** + * @var MockObject|Observer + */ + private $eventObserverMock; + + /** + * @var MockObject|Action + */ + private $controllerMock; + + /** + * @var MockObject|HttpResponse + */ + private $httpResponseMock; + + /** + * @inheritDoc + */ + protected function setUp() + { + $formId = 'backend_forgotpassword'; + $email = 'stub@test.mail'; + $requestParams = ['STUB_PARAM']; + + $this->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); + + $requestMock = $this->createMock(HttpRequest::class); + $requestMock->expects($this->any()) + ->method('getParam') + ->with('email') + ->willReturn($email); + $requestMock->expects($this->any()) + ->method('getParams') + ->willReturn($requestParams); + $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($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->captchaMock->expects($this->once())->method('isRequired')->willReturn(true); + $this->captchaMock->expects($this->once())->method('isCorrect')->willReturn(true); + $this->messageManagerMock->expects($this->never())->method('addErrorMessage'); + $this->httpResponseMock->expects($this->never())->method('setRedirect'); + + $this->observer->execute($this->eventObserverMock); + } + + /** + * Test case when Captcha is required and was entered incorrectly. + */ + public function testExecuteWhenCaptchaIsIncorrect() + { + $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->captchaMock->expects($this->once())->method('isRequired')->willReturn(false); + $this->messageManagerMock->expects($this->never())->method('addErrorMessage'); + $this->httpResponseMock->expects($this->never())->method('setRedirect'); + + $this->observer->execute($this->eventObserverMock); + } +} From c8baed5750f705531e75573ac8a1977dd6fe7d5f Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 5 Feb 2020 13:57:49 +0200 Subject: [PATCH 475/666] MC-30963: [Magento Cloud] CMS blocks with identical identifiers --- .../Magento/Cms/Model/ResourceModel/Block.php | 17 +++++------------ .../Test/Mftf/Test/CheckStaticBlocksTest.xml | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 14 deletions(-) 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/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"> From 17990cb1670acc72e92d568aae43c48f5b5e23ee Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 5 Feb 2020 14:32:24 +0200 Subject: [PATCH 476/666] Add annotation --- .../Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php index 346814aca2084..892494b4db8df 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php @@ -25,6 +25,7 @@ /** * Unit Test for \Magento\Captcha\Observer\CheckUserForgotPasswordBackendObserver + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CheckUserForgotPasswordBackendObserverTest extends TestCase { From 9f9331f8ff926f3be71a56feb26e9a24a49413dc Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 5 Feb 2020 14:59:29 +0200 Subject: [PATCH 477/666] MC-30682: [FT] [MFTF] [2.4] Fix flaky test AdminCreateVirtualProductWithTierPriceForGeneralGroupTest (MC-6033) --- ...AdvancedPricingAddTierPriceActionGroup.xml | 34 ++++ ...mCloseAdvancedPricingDialogActionGroup.xml | 19 +++ ...rmDoneAdvancedPricingDialogActionGroup.xml | 19 +++ ...rmOpenAdvancedPricingDialogActionGroup.xml | 20 +++ ...vancedPricingCheckTierPriceActionGroup.xml | 32 ++++ .../SetProductUrlKeyByStringActionGroup.xml | 2 +- .../Catalog/Test/Mftf/Data/ProductData.xml | 1 + ...AdminProductFormAdvancedPricingSection.xml | 8 + ...roductWithTierPriceForGeneralGroupTest.xml | 157 ++++++++---------- 9 files changed, 200 insertions(+), 92 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormAdvancedPricingAddTierPriceActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormCloseAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormDoneAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductFormOpenAdvancedPricingDialogActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductFormAdvancedPricingCheckTierPriceActionGroup.xml 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/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/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/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index 46bb6e527608f..bc04b3b1dcd0b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -756,6 +756,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/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/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index 4c3d519106389..e4e52272e5935 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 stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> + <deleteData stepKey="deleteCustomer" createDataKey="customer"/> <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="logout" 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"/> - <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"/> + <!-- 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="selectProductStockClass"/> + <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="searchForSimpleProduct"> + <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> From 198d216d2190b804dcec5dde1d22c29dc824efb4 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 5 Feb 2020 15:39:17 +0200 Subject: [PATCH 478/666] cover changes with jasmine test --- .../dynamic-rows-configurable.test.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js new file mode 100644 index 0000000000000..25d49af9b1bc7 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js @@ -0,0 +1,53 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/* eslint-disable max-nested-callbacks */ +define([ + 'jquery', + 'Magento_ConfigurableProduct/js/components/dynamic-rows-configurable', + 'Magento_Ui/js/dynamic-rows/dynamic-rows' +], function ($, DynamicRowsConf, DynamicRows) { + 'use strict'; + + describe('Magento_ConfigurableProduct/js/components/dynamic-rows-configurable', function () { + var model; + + beforeEach(function () { + model = new DynamicRowsConf(new DynamicRows({ + isEmpty: jasmine.createSpy().and.returnValue(1), + isShowAddProductButton: jasmine.createSpy().and.returnValue(1) + })); + + }); + + it('Verify processingUnionInsertDat method', function () { + var expectedData = [], + mockData = [ + { + attributes: 'Color: dsfsd', + sku: 'Conf-sdfs' + }, + { + attributes: 'Color: sdfs', + sku: 'Conf-dsfsd' + } + ], + sourceMock = { + get: jasmine.createSpy().and.returnValue(['code1', 'code2']), + set: jasmine.createSpy().and.callFake(function (path, row) { + expectedData.push(row); + }) + }; + + model.getChildItems = jasmine.createSpy().and.returnValue($('')); + model.source = sourceMock; + model.processingUnionInsertData(mockData); + expect(model.source.get).toHaveBeenCalled(); + expect(model.getChildItems).toHaveBeenCalled(); + expect(expectedData[1].sku).toBe(mockData[0].sku); + }); + + }); +}); From 55337b9f0f1d26a4d11b2edd949adee3af2be8fe Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Wed, 5 Feb 2020 15:42:09 +0200 Subject: [PATCH 479/666] MC-31025: Indexer price calculation for configurable product --- .../Price/GetPriceIndexDataByProductId.php | 77 +++++++ .../Product/Type/Configurable/PriceTest.php | 193 ++++++++++++++++ ...configurable_product_with_percent_rule.php | 50 +++++ ...ble_product_with_percent_rule_rollback.php | 33 +++ ...roduct_with_percent_rules_for_children.php | 66 ++++++ ...th_percent_rules_for_children_rollback.php | 35 +++ .../Product/Type/Configurable/PriceTest.php | 209 ++++++++++-------- ...th_custom_option_and_simple_tier_price.php | 34 +++ ..._option_and_simple_tier_price_rollback.php | 8 + 9 files changed, 608 insertions(+), 97 deletions(-) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Price/GetPriceIndexDataByProductId.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/Model/Product/Type/Configurable/PriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price_rollback.php diff --git a/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Price/GetPriceIndexDataByProductId.php b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Price/GetPriceIndexDataByProductId.php new file mode 100644 index 0000000000000..b1794c55d06f3 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Price/GetPriceIndexDataByProductId.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\TestFramework\Catalog\Model\Product\Price; + +use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver; +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Customer\Model\Indexer\CustomerGroupDimensionProvider; +use Magento\Framework\Indexer\DimensionFactory; +use Magento\Store\Model\Indexer\WebsiteDimensionProvider; + +/** + * Search and return price data from price index table. + */ +class GetPriceIndexDataByProductId +{ + /** + * @var ProductResource + */ + private $productResource; + + /** + * @var PriceTableResolver + */ + private $priceTableResolver; + + /** + * @var DimensionFactory + */ + private $dimensionFactory; + + /** + * @param ProductResource $productResource + * @param PriceTableResolver $priceTableResolver + * @param DimensionFactory $dimensionFactory + */ + public function __construct( + ProductResource $productResource, + PriceTableResolver $priceTableResolver, + DimensionFactory $dimensionFactory + ) { + $this->productResource = $productResource; + $this->priceTableResolver = $priceTableResolver; + $this->dimensionFactory = $dimensionFactory; + } + + /** + * Returns price data by product id. + * + * @param int $productId + * @param int $groupId + * @param int $websiteId + * @return array + */ + public function execute(int $productId, int $groupId, int $websiteId): array + { + $tableName = $this->priceTableResolver->resolve( + 'catalog_product_index_price', + [ + $this->dimensionFactory->create(WebsiteDimensionProvider::DIMENSION_NAME, (string)$websiteId), + $this->dimensionFactory->create(CustomerGroupDimensionProvider::DIMENSION_NAME, (string)$groupId), + ] + ); + + $select = $this->productResource->getConnection()->select() + ->from($tableName) + ->where('entity_id = ?', $productId) + ->where('customer_group_id = ?', $groupId) + ->where('website_id = ?', $websiteId); + + return $this->productResource->getConnection()->fetchAll($select); + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/Model/Product/Type/Configurable/PriceTest.php b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/Model/Product/Type/Configurable/PriceTest.php new file mode 100644 index 0000000000000..1d8264522a2c4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/Model/Product/Type/Configurable/PriceTest.php @@ -0,0 +1,193 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogRuleConfigurable\Model\Product\Type\Configurable; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price; +use Magento\Customer\Model\Group; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Provides tests for configurable product pricing with catalog rules. + * + * @magentoDbIsolation disabled + * @magentoAppArea frontend + */ +class PriceTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var WebsiteRepositoryInterface + */ + private $websiteRepository; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var Price + */ + private $priceModel; + + /** + * @var GetPriceIndexDataByProductId + */ + private $getPriceIndexDataByProductId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->priceModel = $this->objectManager->create(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); + } + + /** + * @magentoDataFixture Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule.php + * @return void + */ + public function testGetFinalPriceWithCustomOptionAndCatalogRule(): void + { + $indexPrices = [ + 'simple_10' => [ + 'price' => 10, + 'final_price' => 9, + 'min_price' => 9, + 'max_price' => 9, + 'tier_price' => null + ], + 'simple_20' => [ + 'price' => 20, + 'final_price' => 15, + 'min_price' => 15, + 'max_price' => 15, + 'tier_price' => 15 + ], + 'configurable' => [ + 'price' => 0, + 'final_price' => 0, + 'min_price' => 9, + 'max_price' => 30, + 'tier_price' => 15 + ], + ]; + $this->assertConfigurableProductPrice(20, 25, $indexPrices); + } + + /** + * @magentoDataFixture Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children.php + * @return void + */ + public function testGetFinalPriceWithCustomOptionAndCatalogRulesForChildren(): void + { + $indexPrices = [ + 'simple_10' => [ + 'price' => 10, + 'final_price' => 4.5, + 'min_price' => 4.5, + 'max_price' => 9, + 'tier_price' => null + ], + 'simple_20' => [ + 'price' => 20, + 'final_price' => 8, + 'min_price' => 8, + 'max_price' => 15, + 'tier_price' => 15 + ], + 'configurable' => [ + 'price' => 0, + 'final_price' => 0, + 'min_price' => 4.5, + 'max_price' => 23, + 'tier_price' => 15 + ], + ]; + $this->assertConfigurableProductPrice(19.5, 23, $indexPrices); + } + + /** + * Asserts configurable product prices. + * + * @param float $priceWithFirstSimple + * @param float $priceWithSecondSimple + * @param array $indexPrices + * @return void + */ + private function assertConfigurableProductPrice( + float $priceWithFirstSimple, + float $priceWithSecondSimple, + array $indexPrices + ): void { + foreach ($indexPrices as $sku => $prices) { + $this->assertIndexTableData($sku, $prices); + } + $configurable = $this->productRepository->get('configurable'); + //Add tier price option + $optionId = $configurable->getOptions()[0]->getId(); + $configurable->addCustomOption(AbstractType::OPTION_PREFIX . $optionId, 'text'); + $configurable->addCustomOption('option_ids', $optionId); + //First simple rule price + Option price + $this->assertFinalPrice($configurable, $priceWithFirstSimple); + $configurable->addCustomOption('simple_product', 20, $this->productRepository->get('simple_20')); + //Second simple rule price + Option price + $this->assertFinalPrice($configurable, $priceWithSecondSimple); + } + + /** + * Asserts product final price. + * + * @param ProductInterface $product + * @param float $expectedPrice + * @return void + */ + private function assertFinalPrice(ProductInterface $product, float $expectedPrice): void + { + $this->assertEquals( + round($expectedPrice, 2), + round($this->priceModel->getFinalPrice(1, $product), 2) + ); + } + + /** + * Asserts price data in index table. + * + * @param string $sku + * @param array $expectedPrices + * @return void + */ + private function assertIndexTableData(string $sku, array $expectedPrices): void + { + $data = $this->getPriceIndexDataByProductId->execute( + (int)$this->productRepository->get($sku)->getId(), + Group::NOT_LOGGED_IN_ID, + (int)$this->websiteRepository->get('base')->getId() + ); + $data = reset($data); + foreach ($expectedPrices as $column => $price) { + $this->assertEquals($price, $data[$column]); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule.php b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule.php new file mode 100644 index 0000000000000..abdf785c447a3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule.php @@ -0,0 +1,50 @@ +<?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\Rule; +use Magento\CatalogRule\Model\Rule\Condition\Combine; +use Magento\CatalogRule\Model\Rule\Condition\Product; +use Magento\CatalogRule\Model\RuleFactory; +use Magento\Customer\Model\Group; +use Magento\Framework\App\Area; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/../../ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php'; +Bootstrap::getInstance()->loadArea(Area::AREA_ADMINHTML); + +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var Rule $rule */ +$rule = $objectManager->get(RuleFactory::class)->create(); +$rule->loadPost( + [ + 'name' => 'Percent rule for configurable product', + 'is_active' => '1', + 'stop_rules_processing' => 0, + 'website_ids' => [$websiteRepository->get('base')->getId()], + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + 'discount_amount' => 50, + 'simple_action' => 'by_percent', + 'from_date' => '', + 'to_date' => '', + 'sort_order' => 0, + 'sub_is_enable' => 0, + 'sub_discount_amount' => 0, + 'conditions' => [ + '1' => ['type' => Combine::class, 'aggregator' => 'all', 'value' => '1', 'new_child' => ''], + '1--1' => ['type' => Product::class, 'attribute' => 'sku', 'operator' => '==', 'value' => 'configurable'], + ], + ] +); +$ruleRepository->save($rule); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule_rollback.php new file mode 100644 index 0000000000000..5b23d1918e394 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rule_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\CatalogRule\Api\CatalogRuleRepositoryInterface; +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory; +use Magento\CatalogRule\Model\Rule; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ + . '/../../ConfigurableProduct/_files/' + . 'configurable_product_with_custom_option_and_simple_tier_price_rollback.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->create(CatalogRuleRepositoryInterface::class); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +/** @var CollectionFactory $ruleCollectionFactory */ +$ruleCollectionFactory = $objectManager->get(CollectionFactory::class); +$ruleCollection = $ruleCollectionFactory->create() + ->addFieldToFilter('name', ['eq' => 'Percent rule for configurable product']) + ->setPageSize(1); +/** @var Rule $rule */ +$rule = $ruleCollection->getFirstItem(); +if ($rule->getId()) { + $ruleRepository->delete($rule); +} +$indexBuilder->reindexFull(); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children.php b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children.php new file mode 100644 index 0000000000000..79a66c69ae618 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children.php @@ -0,0 +1,66 @@ +<?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\Rule; +use Magento\CatalogRule\Model\Rule\Condition\Combine; +use Magento\CatalogRule\Model\Rule\Condition\Product; +use Magento\CatalogRule\Model\RuleFactory; +use Magento\Customer\Model\Group; + +require __DIR__ . '/configurable_product_with_percent_rule.php'; + +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->get(CatalogRuleRepositoryInterface::class); +/** @var Rule $firstRule */ +$ruleFactory = $objectManager->get(RuleFactory::class); + +$firstRule = $ruleFactory->create(); +$firstRule->loadPost( + [ + 'name' => 'Percent rule for first simple product', + 'is_active' => '1', + 'stop_rules_processing' => 0, + 'website_ids' => [$websiteRepository->get('base')->getId()], + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + 'discount_amount' => 10, + 'simple_action' => 'by_percent', + 'from_date' => '', + 'to_date' => '', + 'sort_order' => 0, + 'sub_is_enable' => 0, + 'sub_discount_amount' => 0, + 'conditions' => [ + '1' => ['type' => Combine::class, 'aggregator' => 'all', 'value' => '1', 'new_child' => ''], + '1--1' => ['type' => Product::class, 'attribute' => 'sku', 'operator' => '==', 'value' => 'simple_10'], + ], + ] +); +$ruleRepository->save($firstRule); + +$secondRule = $ruleFactory->create(); +$secondRule->loadPost( + [ + 'name' => 'Percent rule for second simple product', + 'is_active' => '1', + 'stop_rules_processing' => 0, + 'website_ids' => [$websiteRepository->get('base')->getId()], + 'customer_group_ids' => Group::NOT_LOGGED_IN_ID, + 'discount_amount' => 20, + 'simple_action' => 'by_percent', + 'from_date' => '', + 'to_date' => '', + 'sort_order' => 0, + 'sub_is_enable' => 0, + 'sub_discount_amount' => 0, + 'conditions' => [ + '1' => ['type' => Combine::class, 'aggregator' => 'all', 'value' => '1', 'new_child' => ''], + '1--1' => ['type' => Product::class, 'attribute' => 'sku', 'operator' => '==', 'value' => 'simple_20'], + ], + ] +); +$ruleRepository->save($secondRule); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children_rollback.php new file mode 100644 index 0000000000000..773abe6236785 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/_files/configurable_product_with_percent_rules_for_children_rollback.php @@ -0,0 +1,35 @@ +<?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; + +require __DIR__ . '/configurable_product_with_percent_rule_rollback.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CatalogRuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->create(CatalogRuleRepositoryInterface::class); +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +/** @var CollectionFactory $ruleCollectionFactory */ +$ruleCollectionFactory = $objectManager->get(CollectionFactory::class); +$ruleCollection = $ruleCollectionFactory->create() + ->addFieldToFilter( + 'name', + [ + 'in' => [ + 'Percent rule for first simple product', + 'Percent rule for second simple product', + ] + ] + ); +foreach ($ruleCollection as $rule) { + $ruleRepository->delete($rule); +} +$indexBuilder->reindexFull(); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php index e530029e9755e..6f491b33a3496 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php @@ -3,48 +3,94 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product\Type\AbstractType; +use Magento\Customer\Model\Group; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; /** - * Class PriceTest + * Provides tests for configurable product pricing. + * * @magentoDbIsolation disabled */ -class PriceTest extends \PHPUnit\Framework\TestCase +class PriceTest extends TestCase { - /** @var \Magento\Framework\ObjectManagerInterface */ - protected $objectManager; + /** + * @var ObjectManagerInterface + */ + private $objectManager; - /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory */ - protected $customOptionFactory; + /** + * @var ProductRepositoryInterface + */ + private $productRepository; /** - * + * @var Price + */ + private $priceModel; + + /** + * @var GetPriceIndexDataByProductId + */ + private $getPriceIndexDataByProductId; + + /** + * @var WebsiteRepositoryInterface + */ + private $websiteRepository; + + /** + * @inheritdoc */ protected function setUp() { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); + $this->priceModel = $this->objectManager->create(Price::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->getPriceIndexDataByProductId = $this->objectManager->get(GetPriceIndexDataByProductId::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); } /** * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @return void */ - public function testGetFinalPrice() + public function testGetFinalPrice(): void { $this->assertPrice(10); + $this->assertIndexTableData( + 'configurable', + ['price' => 0, 'final_price' => 0, 'min_price' => 10, 'max_price' => 20, 'tier_price' => null] + ); + $this->assertIndexTableData( + 'simple_10', + ['price' => 10, 'final_price' => 10, 'min_price' => 10, 'max_price' => 10, 'tier_price' => null] + ); + $this->assertIndexTableData( + 'simple_20', + ['price' => 20, 'final_price' => 20, 'min_price' => 20, 'max_price' => 20, 'tier_price' => null] + ); } /** * @magentoConfigFixture current_store tax/display/type 1 * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @return void */ - public function testGetFinalPriceExcludingTax() + public function testGetFinalPriceExcludingTax(): void { $this->assertPrice(10); } @@ -53,9 +99,9 @@ public function testGetFinalPriceExcludingTax() * @magentoConfigFixture current_store tax/display/type 2 * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @return void */ - public function testGetFinalPriceIncludingTax() + public function testGetFinalPriceIncludingTax(): void { //lowest price of configurable variation + 10% $this->assertPrice(11); @@ -65,9 +111,9 @@ public function testGetFinalPriceIncludingTax() * @magentoConfigFixture current_store tax/display/type 3 * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @return void */ - public function testGetFinalPriceIncludingExcludingTax() + public function testGetFinalPriceIncludingExcludingTax(): void { //lowest price of configurable variation + 10% $this->assertPrice(11); @@ -76,109 +122,78 @@ public function testGetFinalPriceIncludingExcludingTax() /** * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @return void */ - public function testGetFinalPriceWithSelectedSimpleProduct() + public function testGetFinalPriceWithSelectedSimpleProduct(): void { - $product = $this->getProduct(1); - $product->addCustomOption('simple_product', 20, $this->getProduct(20)); + $product = $this->productRepository->get('configurable'); + $product->addCustomOption('simple_product', 20, $this->productRepository->get('simple_20')); $this->assertPrice(20, $product); } /** - * @magentoConfigFixture current_store tax/display/type 1 - * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php - * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoDbIsolation disabled + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php + * @return void */ - public function testGetFinalPriceWithCustomOption() + public function testGetFinalPriceWithCustomOptionAndSimpleTierPrice(): void { - $product = $this->getProduct(1); - - $options = $this->prepareOptions( - [ - [ - 'option_id' => null, - 'previous_group' => 'text', - 'title' => 'Test Field', - 'type' => 'field', - 'is_require' => 1, - 'sort_order' => 0, - 'price' => 100, - 'price_type' => 'fixed', - 'sku' => '1-text', - 'max_characters' => 100, - ], - ], - $product + $configurable = $this->productRepository->get('configurable'); + $this->assertIndexTableData( + 'configurable', + ['price' => 0, 'final_price' => 0, 'min_price' => 9, 'max_price' => 30, 'tier_price' => 15] ); - - $product->setOptions($options); - $product->setCanSaveCustomOptions(true); - - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - $product = $productRepository->save($product); - - $optionId = $product->getOptions()[0]->getId(); - $product->addCustomOption(AbstractType::OPTION_PREFIX . $optionId, 'text'); - $product->addCustomOption('option_ids', $optionId); - $this->assertPrice(110, $product); + $this->assertIndexTableData( + 'simple_10', + ['price' => 10, 'final_price' => 9, 'min_price' => 9, 'max_price' => 9, 'tier_price' => null] + ); + $this->assertIndexTableData( + 'simple_20', + ['price' => 20, 'final_price' => 15, 'min_price' => 15, 'max_price' => 15, 'tier_price' => 15] + ); + $optionId = $configurable->getOptions()[0]->getId(); + $configurable->addCustomOption(AbstractType::OPTION_PREFIX . $optionId, 'text'); + $configurable->addCustomOption('option_ids', $optionId); + // First simple special price (9) + Option price (15) + $this->assertPrice(24, $configurable); + $configurable->addCustomOption('simple_product', 20, $this->productRepository->get('simple_20')); + // Second simple tier price (15) + Option price (15) + $this->assertPrice(30, $configurable); } /** - * @param array $options - * @param \Magento\Catalog\Model\Product $product - * @return \Magento\Catalog\Api\Data\ProductCustomOptionInterface[] + * Asserts price data in index table. + * + * @param string $sku + * @param array $expectedPrices + * @return void */ - protected function prepareOptions($options, $product) + private function assertIndexTableData(string $sku, array $expectedPrices): void { - $preparedOptions = []; - - if (!$this->customOptionFactory) { - $this->customOptionFactory = $this->objectManager->create( - \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class - ); - } - - foreach ($options as $option) { - $option = $this->customOptionFactory->create(['data' => $option]); - $option->setProductSku($product->getSku()); - - $preparedOptions[] = $option; + $data = $this->getPriceIndexDataByProductId->execute( + (int)$this->productRepository->get($sku)->getId(), + Group::NOT_LOGGED_IN_ID, + (int)$this->websiteRepository->get('base')->getId() + ); + $data = reset($data); + foreach ($expectedPrices as $column => $price) { + $this->assertEquals($price, $data[$column], $column); } - - return $preparedOptions; } /** - * Test + * Asserts product final price. * - * @param $expectedPrice - * @param null $product + * @param float $expectedPrice + * @param ProductInterface|null $product * @return void */ - protected function assertPrice($expectedPrice, $product = null) + private function assertPrice(float $expectedPrice, ?ProductInterface $product = null): void { - $product = $product ?: $this->getProduct(1); - - /** @var $model \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price */ - $model = $this->objectManager->create( - \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price::class - ); - + $product = $product ?: $this->productRepository->get('configurable'); // final price is the lowest price of configurable variations - $this->assertEquals(round($expectedPrice, 2), round($model->getFinalPrice(1, $product), 2)); - } - - /** - * @param int $id - * @return \Magento\Catalog\Model\Product - */ - private function getProduct($id) - { - /** @var $productRepository ProductRepositoryInterface */ - $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); - return $productRepository->getById($id, true, null, true); + $this->assertEquals( + round($expectedPrice, 2), + round($this->priceModel->getFinalPrice(1, $product), 2) + ); } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php new file mode 100644 index 0000000000000..994d1d0f27583 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Customer\Model\Group; +use Magento\Store\Api\WebsiteRepositoryInterface; + +require __DIR__ . '/product_configurable_with_custom_option_type_text.php'; + +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */ +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +/** @var ProductTierPriceExtensionFactory $tpExtensionAttributeFactory */ +$tpExtensionAttributeFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); + +$firstSimple = $productRepository->get('simple_10'); +$firstSimple->setSpecialPrice(9); +$productRepository->save($firstSimple); + +$secondSimple = $productRepository->get('simple_20'); +$tierPriceExtensionAttribute = $tpExtensionAttributeFactory->create( + ['data' => ['website_id' => $websiteRepository->get('admin')->getId(), 'percentage_value' => 25]] +); +$tierPrices[] = $tierPriceFactory + ->create(['data' => ['customer_group_id' => Group::CUST_GROUP_ALL, 'qty' => 1]]) + ->setExtensionAttributes($tierPriceExtensionAttribute); +$secondSimple->setTierPrices($tierPrices); +$productRepository->save($secondSimple); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price_rollback.php new file mode 100644 index 0000000000000..5157ec05a8834 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_custom_option_and_simple_tier_price_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__ . '/product_configurable_with_custom_option_type_text_rollback.php'; From 3262758df6893ebaca2412de9bf03c868d2b8535 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Wed, 5 Feb 2020 15:50:07 +0200 Subject: [PATCH 480/666] Working on static tests --- .../Customer/view/frontend/templates/form/edit.phtml | 4 ++-- .../testsuite/Magento/Customer/Controller/AccountTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) 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 89b86f8af8e55..f69a249764146 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml @@ -40,8 +40,8 @@ use Magento\Customer\Block\Widget\Name; </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" /> + title="<?= $block->escapeHtmlAttr(__('Change Password')) ?>" class="checkbox" + <?php if ($block->getChangePassword()): ?> checked="checked"<?php endif; ?> /> <label class="label" for="change-password"> <span><?= $block->escapeHtml(__('Change Password')) ?></span> </label> diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 84845545d54f3..d009fff880873 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -511,8 +511,8 @@ public function testEditAction() // Verify the password check box is not checked $expectedString = <<<EXPECTED_HTML <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" - title="Change Password" - class="checkbox" /> + title="Change Password" class="checkbox" + /> EXPECTED_HTML; $this->assertContains($expectedString, $body); } @@ -532,8 +532,8 @@ public function testChangePasswordEditAction() // Verify the password check box is checked $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" /> + title="Change Password" class="checkbox" + checked="checked" /> EXPECTED_HTML; $this->assertContains($expectedString, $body); } From 9ebd3e01049fe82a360b8d09190fe3298fbab79d Mon Sep 17 00:00:00 2001 From: Alex Paliarush <paliarus@adobe.com> Date: Tue, 4 Feb 2020 14:38:04 -0600 Subject: [PATCH 481/666] ECP-202 Deprecate Rotation Support in Magento - Fixed static tests --- .../Magento/Catalog/Model/Product/Image.php | 20 +++++++++++++++++-- lib/internal/Magento/Framework/Image.php | 14 ++++++++----- .../Image/Adapter/AbstractAdapter.php | 3 --- .../Image/Adapter/AdapterInterface.php | 3 +++ .../Framework/Image/Adapter/ImageMagick.php | 20 +++++++++++++++---- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Image.php b/app/code/Magento/Catalog/Model/Product/Image.php index 6c7c133223532..7c2a53768fd47 100644 --- a/app/code/Magento/Catalog/Model/Product/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Image.php @@ -10,9 +10,11 @@ use Magento\Catalog\Model\View\Asset\PlaceholderFactory; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Image as MagentoImage; use Magento\Framework\Serialize\SerializerInterface; use Magento\Catalog\Model\Product\Image\ParamsBuilder; +use Magento\Framework\Filesystem\Driver\File as FilesystemDriver; /** * Image operations @@ -200,6 +202,11 @@ class Image extends \Magento\Framework\Model\AbstractModel */ private $serializer; + /** + * @var FilesystemDriver + */ + private $filesystemDriver; + /** * Constructor * @@ -220,6 +227,8 @@ class Image extends \Magento\Framework\Model\AbstractModel * @param array $data * @param SerializerInterface $serializer * @param ParamsBuilder $paramsBuilder + * @param FilesystemDriver $filesystemDriver + * @throws \Magento\Framework\Exception\FileSystemException * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ @@ -240,7 +249,8 @@ public function __construct( \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], SerializerInterface $serializer = null, - ParamsBuilder $paramsBuilder = null + ParamsBuilder $paramsBuilder = null, + FilesystemDriver $filesystemDriver = null ) { $this->_storeManager = $storeManager; $this->_catalogProductMediaConfig = $catalogProductMediaConfig; @@ -255,6 +265,7 @@ public function __construct( $this->viewAssetPlaceholderFactory = $viewAssetPlaceholderFactory; $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); $this->paramsBuilder = $paramsBuilder ?: ObjectManager::getInstance()->get(ParamsBuilder::class); + $this->filesystemDriver = $filesystemDriver ?: ObjectManager::getInstance()->get(FilesystemDriver::class); } /** @@ -666,7 +677,12 @@ public function getDestinationSubdir() public function isCached() { $path = $this->imageAsset->getPath(); - return is_array($this->loadImageInfoFromCache($path)) || file_exists($path); + try { + $isCached = is_array($this->loadImageInfoFromCache($path)) || $this->filesystemDriver->isExists($path); + } catch (FileSystemException $e) { + $isCached = false; + } + return $isCached; } /** diff --git a/lib/internal/Magento/Framework/Image.php b/lib/internal/Magento/Framework/Image.php index ab88f23860704..64cd009a84a3c 100644 --- a/lib/internal/Magento/Framework/Image.php +++ b/lib/internal/Magento/Framework/Image.php @@ -49,7 +49,7 @@ public function open() $this->_adapter->checkDependencies(); if (!file_exists($this->_fileName)) { - throw new \Exception("File '{$this->_fileName}' does not exist."); + throw new \RuntimeException("File '{$this->_fileName}' does not exist."); } $this->_adapter->open($this->_fileName); @@ -95,7 +95,7 @@ public function rotate($angle) /** * Crop an image. * - * @param int $top Default value is 0 + * @param int $top Default value is 0 * @param int $left Default value is 0 * @param int $right Default value is 0 * @param int $bottom Default value is 0 @@ -195,7 +195,7 @@ public function quality($value) * @param int $watermarkImageOpacity Watermark image opacity. * @param bool $repeat Enable or disable watermark brick. * @access public - * @throws \Exception + * @throws \RuntimeException * @return void */ public function watermark( @@ -206,7 +206,7 @@ public function watermark( $repeat = false ) { if (!file_exists($watermarkImage)) { - throw new \Exception("Required file '{$watermarkImage}' does not exists."); + throw new \RuntimeException("Required file '{$watermarkImage}' does not exists."); } $this->_adapter->watermark($watermarkImage, $positionX, $positionY, $watermarkImageOpacity, $repeat); } @@ -233,16 +233,19 @@ public function getImageType() return $this->_adapter->getImageType(); } + // phpcs:disable Magento2.CodeAnalysis.EmptyBlock /** * Process * - * @access public + * @access public, * @return void */ public function process() { } + // phpcs:enable Magento2.CodeAnalysis.EmptyBlock + // phpcs:disable Magento2.CodeAnalysis.EmptyBlock /** * Instruction * @@ -252,6 +255,7 @@ public function process() public function instruction() { } + // phpcs:enable Magento2.CodeAnalysis.EmptyBlock /** * Set image background color diff --git a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php index ecb10c67a7dce..88dbd69405471 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php +++ b/lib/internal/Magento/Framework/Image/Adapter/AbstractAdapter.php @@ -41,9 +41,6 @@ abstract class AbstractAdapter implements AdapterInterface const POSITION_CENTER = 'center'; - /** - * Default font size - */ const DEFAULT_FONT_SIZE = 15; /** diff --git a/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php b/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php index 7749664e520d0..736686968b374 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php +++ b/lib/internal/Magento/Framework/Image/Adapter/AdapterInterface.php @@ -28,6 +28,8 @@ interface AdapterInterface public function getColorAt($x, $y); /** + * Render image and return its binary contents + * * @see \Magento\Framework\Image\Adapter\AbstractAdapter::getImage * @return string */ @@ -99,6 +101,7 @@ public function crop($top = 0, $left = 0, $right = 0, $bottom = 0); /** * Save image to specific path. + * * If some folders of path does not exist they will be created * * @param null|string $destination diff --git a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php index 418230675e356..a08d83d33b0ef 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php +++ b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php @@ -5,6 +5,11 @@ */ namespace Magento\Framework\Image\Adapter; +/** + * Wrapper for Imagick image processing PHP Extension. + * + * @link https://www.php.net/manual/en/book.imagick.php + */ class ImageMagick extends \Magento\Framework\Image\Adapter\AbstractAdapter { /** @@ -77,7 +82,11 @@ public function open($filename) try { $this->_imageHandler = new \Imagick($this->_fileName); } catch (\ImagickException $e) { - throw new \Exception(sprintf('Unsupported image format. File: %s', $this->_fileName), $e->getCode(), $e); + throw new \RuntimeException( + sprintf('Unsupported image format. File: %s', $this->_fileName), + $e->getCode(), + $e + ); } $this->backgroundColor(); @@ -86,6 +95,7 @@ public function open($filename) /** * Save image to specific path. + * * If some folders of path does not exist they will be created * * @param null|string $destination @@ -124,6 +134,8 @@ protected function _applyOptions() } /** + * Render image binary content and return it. + * * @see \Magento\Framework\Image\Adapter\AbstractAdapter::getImage * @return string */ @@ -334,7 +346,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } } catch (\ImagickException $e) { - throw new \Exception('Unable to create watermark.', $e->getCode(), $e); + throw new \RuntimeException('Unable to create watermark.', $e->getCode(), $e); } // merge layers @@ -347,12 +359,12 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = * Checks required dependencies * * @return void - * @throws \Exception If some of dependencies are missing + * @throws \RuntimeException If some of dependencies are missing */ public function checkDependencies() { if (!class_exists('\Imagick', false)) { - throw new \Exception("Required PHP extension 'Imagick' was not loaded."); + throw new \RuntimeException("Required PHP extension 'Imagick' was not loaded."); } } From 0d17e0af1904c1a8a7ac6aadd6280faa527ef1f8 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 5 Feb 2020 16:19:39 +0200 Subject: [PATCH 482/666] Add a new test case, refactoring --- ...kUserForgotPasswordBackendObserverTest.php | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php index 892494b4db8df..584e7eb2e215f 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserForgotPasswordBackendObserverTest.php @@ -29,6 +29,9 @@ */ class CheckUserForgotPasswordBackendObserverTest extends TestCase { + const STUB_EMAIL = 'stub@test.mail'; + const STUB_REQUEST_PARAMS = ['STUB_PARAM']; + /** * @var MockObject|DataHelper */ @@ -60,7 +63,7 @@ class CheckUserForgotPasswordBackendObserverTest extends TestCase private $observer; /** - * @var MockObject + * @var MockObject|CaptchaInterface */ private $captchaMock; @@ -79,14 +82,17 @@ class CheckUserForgotPasswordBackendObserverTest extends TestCase */ private $httpResponseMock; + /** + * @var MockObject|HttpRequest + */ + private $requestMock; + /** * @inheritDoc */ protected function setUp() { $formId = 'backend_forgotpassword'; - $email = 'stub@test.mail'; - $requestParams = ['STUB_PARAM']; $this->helperMock = $this->createMock(DataHelper::class); $this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class); @@ -116,14 +122,7 @@ protected function setUp() ->with($formId) ->willReturn($this->captchaMock); - $requestMock = $this->createMock(HttpRequest::class); - $requestMock->expects($this->any()) - ->method('getParam') - ->with('email') - ->willReturn($email); - $requestMock->expects($this->any()) - ->method('getParams') - ->willReturn($requestParams); + $this->requestMock = $this->createMock(HttpRequest::class); $this->httpResponseMock = $this->createMock(HttpResponse::class); $this->controllerMock = $this->getMockBuilder(Action::class) @@ -132,7 +131,7 @@ protected function setUp() ->getMockForAbstractClass(); $this->controllerMock->expects($this->any()) ->method('getRequest') - ->willReturn($requestMock); + ->willReturn($this->requestMock); $this->controllerMock->expects($this->any()) ->method('getResponse') ->willReturn($this->httpResponseMock); @@ -148,12 +147,11 @@ protected function setUp() */ public function testExecuteWhenCaptchaIsCorrect() { + $this->configureRequestMockWithStubValues(); $this->captchaMock->expects($this->once())->method('isRequired')->willReturn(true); $this->captchaMock->expects($this->once())->method('isCorrect')->willReturn(true); - $this->messageManagerMock->expects($this->never())->method('addErrorMessage'); - $this->httpResponseMock->expects($this->never())->method('setRedirect'); - $this->observer->execute($this->eventObserverMock); + $this->executeOriginalMethodExpectsNoError(); } /** @@ -161,6 +159,7 @@ public function testExecuteWhenCaptchaIsCorrect() */ public function testExecuteWhenCaptchaIsIncorrect() { + $this->configureRequestMockWithStubValues(); $this->captchaMock->expects($this->once())->method('isRequired')->willReturn(true); $this->captchaMock->expects($this->once())->method('isCorrect')->willReturn(false); @@ -180,7 +179,49 @@ public function testExecuteWhenCaptchaIsIncorrect() */ 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'); From d2c8006d935011a3d41cf86937967faca3f7e41f Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 5 Feb 2020 16:22:10 +0200 Subject: [PATCH 483/666] add "&" to test case --- .../web/js/components/dynamic-rows-configurable.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js index 25d49af9b1bc7..4e843dc4c888d 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js @@ -27,7 +27,7 @@ define([ mockData = [ { attributes: 'Color: dsfsd', - sku: 'Conf-sdfs' + sku: 'Conf&-sdfs' }, { attributes: 'Color: sdfs', From 8f802953efa422a36e677a014c6c492f823f93ab Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 5 Feb 2020 14:06:40 +0200 Subject: [PATCH 484/666] fix static --- .../Ui/TemplateEngine/Xhtml/Result.php | 2 +- .../Unit/TemplateEngine/Xhtml/ResultTest.php | 32 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php index df3bdd8f8be6d..1fb79ce6d7653 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -16,7 +16,7 @@ use Psr\Log\LoggerInterface; /** - * Class Result + * @inheritdoc */ class Result implements ResultInterface { diff --git a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php index 47c7bae9934ae..5f73fa8f0fcd3 100644 --- a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -7,17 +7,17 @@ namespace Magento\Ui\Test\Unit\TemplateEngine\Xhtml; use Magento\Framework\App\State; +use Magento\Framework\Serialize\Serializer\JsonHexTag; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Framework\View\Element\UiComponentInterface; use Magento\Framework\View\Layout\Generator\Structure; 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 Magento\Framework\Serialize\Serializer\JsonHexTag; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -use Magento\Framework\DataObject; /** * Test for \Magento\Ui\TemplateEngine\Xhtml\Result. @@ -26,6 +26,11 @@ */ class ResultTest extends TestCase { + /** + * Stub simple html element + */ + private const STUB_HTML_ELEMENT = '<div id="id"></div>'; + /** * @var Result */ @@ -78,7 +83,7 @@ protected function setUp() { $this->templateMock = $this->createMock(Template::class); $this->compilerMock = $this->createMock(CompilerInterface::class); - $this->componentMock = $this->createMock(\Magento\Ui\Component\Listing::class); + $this->componentMock = $this->createMock(Listing::class); $this->structureMock = $this->createMock(Structure::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->stateMock = $this->createMock(State::class); @@ -111,8 +116,13 @@ public function testToStringWithException(): void $this->templateMock->expects($this->once()) ->method('getDocumentElement') ->willThrowException($exception); - $this->stateMock->method('getMode')->willReturn(State::MODE_DEVELOPER); + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($exception); $this->assertEquals( '<pre><code>' . $exception->__toString() . '</code></pre>', $this->model->__toString() @@ -127,20 +137,24 @@ public function testToStringWithException(): void public function testToString(): void { $domElementMock = $this->getMockBuilder(\DOMElement::class) - ->setConstructorArgs(['a']) + ->setConstructorArgs(['arg']) ->getMock(); - $this->templateMock->expects($this->exactly(2)) + $this->templateMock->expects($this->once()) ->method('getDocumentElement') ->willReturn($domElementMock); $this->compilerMock->expects($this->once()) ->method('compile') ->with( - $this->isInstanceOf('\DOMElement'), - $this->componentMock, + $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('string', $this->model->__toString()); + $this->assertEquals(self::STUB_HTML_ELEMENT, $this->model->__toString()); } } From 10363f51cf0b90f99e242601ad0a548bb787c02b Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 5 Feb 2020 16:25:50 +0200 Subject: [PATCH 485/666] Unit test for \Magento\Captcha\Observer\ResetAttemptForBackendObserver and \Magento\Captcha\Observer\ResetAttemptForFrontendObserver --- .../ResetAttemptForBackendObserverTest.php | 53 +++++++++++++++++++ .../ResetAttemptForFrontendObserverTest.php | 52 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php 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..b7a0c9534598d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Captcha\Test\Unit\Observer; + +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Captcha\Observer\ResetAttemptForBackendObserver; +use Magento\Framework\Event; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Captcha\Observer\ResetAttemptForBackendObserver + */ +class ResetAttemptForBackendObserverTest extends TestCase +{ + /** + * Test that the method resets attempts for Backend + */ + public function testExecuteExpectsDeleteUserAttemptsCalled() + { + $logMock = $this->createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts'); + + $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] + ); + $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..f83341eb8680d --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Captcha\Test\Unit\Observer; + +use Magento\Captcha\Model\ResourceModel\Log; +use Magento\Captcha\Model\ResourceModel\LogFactory; +use Magento\Captcha\Observer\ResetAttemptForFrontendObserver; +use Magento\Customer\Model\Customer; +use Magento\Framework\Event\Observer; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit test for \Magento\Captcha\Observer\ResetAttemptForFrontendObserver + */ +class ResetAttemptForFrontendObserverTest extends TestCase +{ + /** + * Test that the method resets attempts for Frontend + */ + public function testExecuteExpectsDeleteUserAttemptsCalled() + { + $logMock = $this->createMock(Log::class); + $logMock->expects($this->once())->method('deleteUserAttempts'); + + $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] + ); + $observer->execute($eventObserverMock); + } +} From 861f4922e0a45d0ab4cf52895043a92019bc09b4 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 5 Feb 2020 16:33:13 +0200 Subject: [PATCH 486/666] small improvements --- .../web/js/components/dynamic-rows-configurable.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js index 4e843dc4c888d..546392d35fe84 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.test.js @@ -46,7 +46,7 @@ define([ model.processingUnionInsertData(mockData); expect(model.source.get).toHaveBeenCalled(); expect(model.getChildItems).toHaveBeenCalled(); - expect(expectedData[1].sku).toBe(mockData[0].sku); + expect(expectedData[1].sku).toBe('Conf&-sdfs'); }); }); From 25886c2d3dd819a65db4a92a888db0d767c53b3b Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Wed, 5 Feb 2020 09:33:05 -0600 Subject: [PATCH 487/666] MC-30236: Upgrade from 2.3.x CE with SD to 2.3.x EE AreaCode Exception - log cache status of only specific types --- setup/src/Magento/Setup/Model/Installer.php | 28 +++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index ee7d5a196127b..2492248551461 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -885,9 +885,11 @@ public function installDataFixtures(array $request = []) $setup = $this->dataSetupFactory->create(); $this->checkFilePermissionsForDbUpgrade(); $this->log->log('Data install/update:'); - $this->updateCaches(false, $frontendCaches, false); + $this->log->log('Disabling caches:'); + $this->updateCaches(false, $frontendCaches); $this->handleDBSchemaData($setup, 'data', $request); - $this->updateCaches(true, $frontendCaches, false); + $this->log->log('Enabling caches:'); + $this->updateCaches(true, $frontendCaches); $registry->unregister('setup-mode-enabled'); } @@ -1266,25 +1268,31 @@ public function uninstall() * * @param bool $isEnabled * @param array $types - * @param bool $logStatus * @return void */ - private function updateCaches($isEnabled, $types = [], $logStatus = true) + private function updateCaches($isEnabled, $types = []) { /** @var \Magento\Framework\App\Cache\Manager $cacheManager */ $cacheManager = $this->objectManagerProvider->get()->create(\Magento\Framework\App\Cache\Manager::class); - $types = empty($types) ? $cacheManager->getAvailableTypes() : $types; + $types = empty($types) ? $cacheManager->getAvailableTypes() : $types; $enabledTypes = $cacheManager->setEnabled($types, $isEnabled); if($isEnabled){ $cacheManager->clean($enabledTypes); } - if ($logStatus) { - $this->log->log('Current status:'); - // phpcs:ignore Magento2.Functions.DiscouragedFunction - $this->log->log(print_r($cacheManager->getStatus(), true)); - } + // 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($cacheStatus, true)); } /** From f3c8d794eef3621f7a2081376b94c9c36d77c89f Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Wed, 5 Feb 2020 18:37:21 +0200 Subject: [PATCH 488/666] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- ...leteProductAttributeByLabelActionGroup.xml | 31 +++++++++++++++++++ ...leteProductAttributeByLabelActionGroup.xml | 2 +- .../Mftf/Test/AdminCreateImageSwatchTest.xml | 8 ++++- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml 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..7898fae279eaf --- /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"/> + </arguments> + + <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> + <waitForPageLoad stepKey="waitForProductAttributeGridPageLoad"/> + <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="{{ModalConfirmationSection.modalContent}}" stepKey="waitForConfirmationPopUpVisible"/> + <click selector="{{ModalConfirmationSection.OkButton}}" stepKey="clickOnConfirmationButton"/> + <waitForPageLoad stepKey="waitForAttributeGridPageLoad"/> + <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" stepKey="waitForSuccessMessageVisible"/> + <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You deleted the product attribute." stepKey="seeAttributeDeleteSuccessMessage"/> + </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/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 8a2683af83dc1..34eaa2f34ba17 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -24,7 +24,13 @@ </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"> + <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> + </actionGroup> + <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> <!-- Begin creating a new product attribute of type "Image Swatch" --> From 64cb774f748d375f72e2e0052261d907f6b23c87 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Wed, 5 Feb 2020 10:40:51 -0600 Subject: [PATCH 489/666] magento/magento2#9466: Fixed unit test --- .../Test/Unit/Model/Product/CopierTest.php | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) 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 1d5abd817deb5..b72ecbf195d39 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -19,22 +19,22 @@ class CopierTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $optionRepositoryMock; + private $optionRepositoryMock; /** * @var Copier */ - protected $_model; + private $_model; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $copyConstructorMock; + private $copyConstructorMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $productFactoryMock; + private $productFactoryMock; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -44,12 +44,12 @@ class CopierTest extends \PHPUnit\Framework\TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $productMock; + private $productMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $metadata; + private $metadata; protected function setUp() { @@ -77,13 +77,10 @@ protected function setUp() $this->_model = new Copier( $this->copyConstructorMock, $this->productFactoryMock, - $this->scopeOverriddenValueMock + $this->scopeOverriddenValueMock, + $this->optionRepositoryMock, + $metadataPool ); - - $this->setProperties($this->_model, [ - 'optionRepository' => $this->optionRepositoryMock, - 'metadataPool' => $metadataPool - ]); } /** @@ -340,20 +337,4 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl() $this->expectException(\Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException::class); $this->_model->copy($this->productMock); } - - /** - * @param $object - * @param array $properties - */ - private function setProperties($object, $properties = []) - { - $reflectionClass = new \ReflectionClass(get_class($object)); - foreach ($properties as $key => $value) { - if ($reflectionClass->hasProperty($key)) { - $reflectionProperty = $reflectionClass->getProperty($key); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($object, $value); - } - } - } } From 4e1bfdeda9d7da91509a3f738e881ad92614a577 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Wed, 5 Feb 2020 18:51:18 +0530 Subject: [PATCH 490/666] Deprecated redundant class --- .../Magento/Sales/Model/Order/Email/Sender/ShipmentSender.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From 0f041810595f18e7d6909ec9a6b0c1897efb7f8f Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Fri, 24 Jan 2020 14:40:56 -0600 Subject: [PATCH 491/666] MQE-1965: Paypal test leveraging AWS Secrets Manager - PayPalSmartButtonInCheckoutPage Unskipped and fixed selectors to test AWS Secret Manager CI --- .../StorefrontPayOrderOnPayPalCheckoutActionGroup.xml | 1 + .../Mftf/Section/PayPalExpressCheckoutConfigSection.xml | 8 ++++---- .../StorefrontPaypalSmartButtonInCheckoutPageTest.xml | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) 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/StorefrontPaypalSmartButtonInCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml index 6adba94e96890..fea1cf3966b99 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> From dc12da03725effe3acc36ce223351338dc017b88 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 5 Feb 2020 14:42:52 -0600 Subject: [PATCH 492/666] MQE-1987: Bump MFTF version and deliver Magento branches 2.6.0 version bump + paypal test --- composer.json | 2 +- composer.lock | 170 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 159 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index 9cbbf1689738f..577987067dc76 100644 --- a/composer.json +++ b/composer.json @@ -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.0", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index 5b94f60fa80a9..dd59126b96caa 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": "27452593216dfff37ed2a7f2aea0237c", "packages": [ { "name": "braintree/braintree_php", @@ -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" }, { @@ -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", @@ -7356,26 +7442,29 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.5.4", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "4f482ce22a755a812b76f81020ae71d502f9d043" + "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262" }, "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/3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", + "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", "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", @@ -7430,7 +7519,7 @@ "magento", "testing" ], - "time": "2019-12-12T20:14:00+00:00" + "time": "2020-02-05T15:53:02+00:00" }, { "name": "mikey179/vfsstream", @@ -7478,6 +7567,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", @@ -8063,20 +8209,20 @@ "authors": [ { "name": "Manuel Pichler", + "role": "Project Founder", "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" + "homepage": "https://github.com/manuelpichler" }, { "name": "Marc Würth", + "role": "Project Maintainer", "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" + "homepage": "https://github.com/ravage84" }, { "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" + "role": "Contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors" } ], "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", From f8bcd47e0959bf34b1f2f01712c0488e0939e881 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Thu, 6 Feb 2020 09:05:09 +0200 Subject: [PATCH 493/666] Update getCustomer method in order class Fix static test --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 0a727b7560396..8a760065439d6 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = parent::getShippingMethod(); + $shippingMethod = $this->getData('shipping_method'); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From da1c926cd6297775a593159d885d995f98580d1d Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Thu, 6 Feb 2020 09:14:31 +0200 Subject: [PATCH 494/666] Revert "Working on static tests" This reverts commit 3262758df6893ebaca2412de9bf03c868d2b8535. --- .../Customer/view/frontend/templates/form/edit.phtml | 4 ++-- .../testsuite/Magento/Customer/Controller/AccountTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) 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 f69a249764146..89b86f8af8e55 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/edit.phtml @@ -40,8 +40,8 @@ use Magento\Customer\Block\Widget\Name; </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')) ?>" class="checkbox" - <?php if ($block->getChangePassword()): ?> checked="checked"<?php endif; ?> /> + 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> diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index d009fff880873..84845545d54f3 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -511,8 +511,8 @@ public function testEditAction() // Verify the password check box is not checked $expectedString = <<<EXPECTED_HTML <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" - title="Change Password" class="checkbox" - /> + title="Change Password" + class="checkbox" /> EXPECTED_HTML; $this->assertContains($expectedString, $body); } @@ -532,8 +532,8 @@ public function testChangePasswordEditAction() // Verify the password check box is checked $expectedString = <<<EXPECTED_HTML <input type="checkbox" name="change_password" id="change-password" data-role="change-password" value="1" - title="Change Password" class="checkbox" - checked="checked" /> + title="Change Password" + checked="checked" class="checkbox" /> EXPECTED_HTML; $this->assertContains($expectedString, $body); } From 89b0a9d4edd2380672ee813d812fe8fbf715eb61 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 11:04:29 +0200 Subject: [PATCH 495/666] refactoring, fix unit test --- .../Test/Unit/Model/Product/CopierTest.php | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) 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 34fddc06f1c42..a1cbc59e56300 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php @@ -5,10 +5,18 @@ */ 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\Copier; +use Magento\Catalog\Model\Product\CopyConstructorInterface; +use Magento\Catalog\Model\Product\Option\Repository; +use Magento\Catalog\Model\ProductFactory; +use Magento\CatalogInventory\Api\Data\StockItemInterface; +use Magento\Framework\EntityManager\EntityMetadata; +use Magento\Framework\EntityManager\MetadataPool; +use PHPUnit\Framework\MockObject\MockObject; /** * Test for Magento\Catalog\Model\Product\Copier class. @@ -18,62 +26,60 @@ class CopierTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ - protected $optionRepositoryMock; + private $optionRepositoryMock; /** * @var Copier */ - protected $_model; + private $_model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ - protected $copyConstructorMock; + private $copyConstructorMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ - protected $productFactoryMock; + private $productFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ - protected $productMock; + private $productMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ - protected $metadata; + private $metadata; /** - * @var ScopeOverriddenValue|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeOverriddenValue|MockObject */ private $scopeOverriddenValue; + /** + * @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->optionRepositoryMock = $this->createMock( - \Magento\Catalog\Model\Product\Option\Repository::class - ); - $this->optionRepositoryMock; + $this->metadata = $this->createMock(EntityMetadata::class); + $metadataPool = $this->createMock(MetadataPool::class); + + $this->copyConstructorMock = $this->createMock(CopyConstructorInterface::class); + $this->productFactoryMock = $this->createPartialMock(ProductFactory::class, ['create']); + $this->optionRepositoryMock = $this->createMock(Repository::class); $this->productMock = $this->createMock(Product::class); - $this->productMock->expects($this->any())->method('getEntityId')->willReturn(1); $this->scopeOverriddenValue = $this->createMock(ScopeOverriddenValue::class); - $this->metadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadata::class) - ->disableOriginalConstructor() - ->getMock(); - $metadataPool = $this->getMockBuilder(\Magento\Framework\EntityManager\MetadataPool::class) - ->disableOriginalConstructor() - ->getMock(); - $metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata); + $this->productMock->expects($this->any()) + ->method('getEntityId') + ->willReturn(1); + $metadataPool->expects($this->any()) + ->method('getMetadata') + ->willReturn($this->metadata); $this->_model = new Copier( $this->copyConstructorMock, @@ -95,9 +101,8 @@ protected function setUp() */ public function testCopy() { - $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 @@ -179,6 +184,9 @@ public function testCopy() 'setUrlKey', 'setStoreId', 'getStoreIds', + 'setMetaTitle', + 'setMetaKeyword', + 'setMetaDescription' ] ); $this->productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($duplicateMock)); @@ -216,7 +224,6 @@ public function testCopy() $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)); } From 80c737a7287439876f73ab90c7fce7e1a5a43877 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:27:53 +0000 Subject: [PATCH 496/666] roll back changes --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 8a760065439d6..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = $this->getData('shipping_method'); + $shippingMethod = parent::getShippingMethod(); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 5a1f48e1cc590a9605c0ae82844e89a9b74e84f6 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:44:35 +0000 Subject: [PATCH 497/666] Revert "Update getCustomer method in order class" This reverts commit f8bcd47e0959bf34b1f2f01712c0488e0939e881. --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 8a760065439d6..0a727b7560396 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = $this->getData('shipping_method'); + $shippingMethod = parent::getShippingMethod(); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 3ca45d8efa0a2a79c207451428b845d34c1addc8 Mon Sep 17 00:00:00 2001 From: Fanis Strezos <fanis.strezos@dotdigital.com> Date: Thu, 6 Feb 2020 09:46:51 +0000 Subject: [PATCH 498/666] Revert "roll back changes" This reverts commit 80c737a7287439876f73ab90c7fce7e1a5a43877. --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 0a727b7560396..8a760065439d6 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -1326,7 +1326,7 @@ public function getTrackingNumbers() */ public function getShippingMethod($asObject = false) { - $shippingMethod = parent::getShippingMethod(); + $shippingMethod = $this->getData('shipping_method'); if (!$asObject || !$shippingMethod) { return $shippingMethod; } else { From 0471a013302ebbd14163c6de55e6e9f008dabffa Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 6 Feb 2020 12:11:20 +0200 Subject: [PATCH 499/666] MC-30682: [FT] [MFTF] [2.4] Fix flaky test AdminCreateVirtualProductWithTierPriceForGeneralGroupTest (MC-6033) --- ...eateVirtualProductWithTierPriceForGeneralGroupTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml index e4e52272e5935..b2ddaac65d070 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceForGeneralGroupTest.xml @@ -25,8 +25,8 @@ <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> <after> - <deleteData stepKey="deleteSimpleSubCategory" createDataKey="categoryEntity"/> - <deleteData stepKey="deleteCustomer" createDataKey="customer"/> + <deleteData createDataKey="categoryEntity" stepKey="deleteSimpleSubCategory"/> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> <actionGroup ref="DeleteProductUsingProductGridActionGroup" stepKey="deleteVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> @@ -50,7 +50,7 @@ <argument name="amount" value="{{tierPriceOnGeneralGroup.price}}"/> </actionGroup> <actionGroup ref="AdminProductFormDoneAdvancedPricingDialogActionGroup" stepKey="doneAdvancedPricingModal"/> - <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductStockClass"/> + <selectOption selector="{{AdminProductFormSection.productTaxClass}}" userInput="{{virtualProductGeneralGroup.productTaxClass}}" stepKey="selectProductTaxClass"/> <actionGroup ref="SetCategoryByNameActionGroup" stepKey="setNewCategory"> <argument name="categoryName" value="$categoryEntity.name$"/> </actionGroup> @@ -61,7 +61,7 @@ <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductAndCheckSuccessMessage"/> <!-- Search created virtual product(from above steps) in the grid --> - <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForSimpleProduct"> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="searchForVirtualProduct"> <argument name="product" value="virtualProductGeneralGroup"/> </actionGroup> From 999fe16ae5ce78bff55a9c71f186cea70fedf128 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 6 Feb 2020 12:59:00 +0200 Subject: [PATCH 500/666] MC-30384: [2.4] Test StorefrontInactiveCatalogRuleTest fails on Jenkins (MC-79) --- .../StorefrontInactiveCatalogRuleTest.xml | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 3423baf7970eb..32cdb4869ddde 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -16,55 +16,53 @@ <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="logout" 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="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> + + <actionGroup ref="StorefrontOpenCartPageActionGroup" stepKey="openCartPage" /> + <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalAppears"/> + <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$createProduct.price$" stepKey="seeProductPriceOnCartPage"/> </test> </tests> From 473858a2538ae22c6cd2a4e07c8a7f5710e91183 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 6 Feb 2020 14:24:04 +0200 Subject: [PATCH 501/666] MC-24260: Automate (convert) integration test MC-26219 --- .../_files/product_with_varchar_attribute.php | 28 +++++++++++++ ...roduct_with_varchar_attribute_rollback.php | 9 +++++ .../Model/Import/ProductTest.php | 40 ++++++++++++++++--- ...ort_product_with_empty_attribute_value.csv | 2 + 4 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_product_with_empty_attribute_value.csv 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..7cc6b9fac4fe1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_varchar_attribute.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Eav\Model\Config; + +require __DIR__ . '/product_varchar_attribute.php'; +require __DIR__ . '/product_simple.php'; + +/** @var Config $eavConfig */ +$eavConfig = $objectManager->create(Config::class); + +$attributeCode = 'varchar_attribute'; +/** @var ProductAttributeInterface $varcharAttribute */ +$varcharAttribute = $attributeRepository->get($attributeCode); +$varcharAttribute->setDefaultValue('Varchar default value'); +$attributeRepository->save($varcharAttribute); +$eavConfig->clear(); + +/** @var ProductInterface $simpleProduct */ +$simpleProduct = $productRepository->get('simple'); +$simpleProduct->setCustomAttribute($attributeCode, $attributeRepository->get($attributeCode)->getDefaultValue()); +$productRepository->save($simpleProduct); 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..64ac63a7e3790 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,6 +13,7 @@ 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; @@ -30,6 +26,7 @@ use Magento\Framework\Filesystem; use Magento\Framework\Registry; 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 +35,8 @@ use Psr\Log\LoggerInterface; /** - * Class ProductTest + * Integration test for \Magento\CatalogImportExport\Model\Import\Product class. + * * @magentoAppIsolation enabled * @magentoDbIsolation enabled * @magentoAppArea adminhtml @@ -81,6 +79,14 @@ class ProductTest extends \Magento\TestFramework\Indexer\TestCase */ private $logger; + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @inheritdoc + */ protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); @@ -92,6 +98,7 @@ protected function setUp() ['logger' => $this->logger] ); $this->importedProducts = []; + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); parent::setUp(); } @@ -3023,4 +3030,25 @@ 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__ . '/_files/' . '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(); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $simpleProduct = $productRepository->get('simple', false, null, true); + $this->assertEquals('Varchar default value', $simpleProduct->getData('varchar_attribute')); + } } 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..11c8e294bb71a --- /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,product_type,attribute_set_code,price,qty,additional_attributes +simple,Simple Product,simple,Default,10,100,varchar_attribute= From 0ed2bcdf447d1edd60326670a4327d3be66b72d5 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 14:34:55 +0200 Subject: [PATCH 502/666] Cover changes with jasmine test --- .../view/frontend/web/js/cookie-status.js | 14 ++++--- .../frontend/web/js/cookie-status.test.js | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js diff --git a/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js index 48d201af0cffe..3726996a862c6 100644 --- a/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js +++ b/app/code/Magento/Theme/view/frontend/web/js/cookie-status.js @@ -1,8 +1,8 @@ define([ 'jquery', 'Magento_Ui/js/modal/modal', - 'mage/translate', -], function($, modal){ + 'mage/translate' +], function ($, modal) { 'use strict'; $.widget('mage.cookieStatus', { @@ -14,6 +14,10 @@ define([ buttons: [{ text: $.mage.__('Close'), class: 'cookie-status', + + /** + * Callback for click event + */ click: function () { this.closeModal(); } @@ -26,11 +30,11 @@ define([ */ _init: function () { - if(!navigator.cookieEnabled) { + if (!navigator.cookieEnabled) { modal(this.options, $('#cookie-status')); } } }); - + return $.mage.cookieStatus; -}); \ No newline at end of file +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js new file mode 100644 index 0000000000000..bd35e0d0bd9f5 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js @@ -0,0 +1,39 @@ + +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'cookieStatus' +], function ($, Cookie) { + 'use strict'; + + describe('Magento_Theme/js/cookie-status', function () { + var widget, + htmlContainer = '<div id="cookie-status" style="display: none"></div>', + navigator; + + beforeEach(function () { + $(document.body).append(htmlContainer); + widget = new Cookie(); + navigator = window.navigator; + }); + + afterEach(function () { + window.navigator = navigator; + }); + + it('verify cookie-status initialization', function () { + expect($.fn.cookieStatus).toBeDefined(); + window.navigator = { + cookieEnabled: false + }; + widget._init(); + expect($('.cookie-status').length).toBe(1); + expect($(document.body).html()).toContain('<aside role="dialog" class="modal-popup'); + }); + + }); +}); From 2f591a8805a03ca0479724a695baeb67586a2e59 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Thu, 6 Feb 2020 18:33:59 +0530 Subject: [PATCH 503/666] Deprecated associated test class --- .../Unit/Model/Order/Email/Sender/ShipmentSenderTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 { From 1692711ef4ab9368c58b3d7a640ebf995818c53d Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 15:41:33 +0200 Subject: [PATCH 504/666] refactor per review commet, add new cases --- .../view/frontend/web/js/cookie-status.test.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js index bd35e0d0bd9f5..03c6b5f57dc07 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js @@ -25,13 +25,25 @@ define([ window.navigator = navigator; }); - it('verify cookie-status initialization', function () { + it('verify initialization cookieStatus widget', function () { + expect($.fn.cookieStatus).toBeDefined(); + }); + + it('verify that modal does not shows when cookies are supported', function () { + expect($.fn.cookieStatus).toBeDefined(); + window.navigator = { + cookieEnabled: true + }; + widget._init(); + expect($(document.body).html()).not.toContain('<aside role="dialog" class="modal-popup'); + }); + + it('shows the modal when cookies are not supported', function () { expect($.fn.cookieStatus).toBeDefined(); window.navigator = { cookieEnabled: false }; widget._init(); - expect($('.cookie-status').length).toBe(1); expect($(document.body).html()).toContain('<aside role="dialog" class="modal-popup'); }); From 78e138675193a41a65ee2f7f8b96fae21101a016 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 15:42:37 +0200 Subject: [PATCH 505/666] remove duplicated check --- .../Magento/Theme/view/frontend/web/js/cookie-status.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js index 03c6b5f57dc07..3002122e3455f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js @@ -30,7 +30,6 @@ define([ }); it('verify that modal does not shows when cookies are supported', function () { - expect($.fn.cookieStatus).toBeDefined(); window.navigator = { cookieEnabled: true }; @@ -39,7 +38,6 @@ define([ }); it('shows the modal when cookies are not supported', function () { - expect($.fn.cookieStatus).toBeDefined(); window.navigator = { cookieEnabled: false }; From 1b1c8bf17bfd4b1a252395f33593faedbcce49f1 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 15:54:16 +0200 Subject: [PATCH 506/666] rename tests --- .../Magento/Theme/view/frontend/web/js/cookie-status.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js index 3002122e3455f..9b302d91d2007 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js @@ -25,11 +25,11 @@ define([ window.navigator = navigator; }); - it('verify initialization cookieStatus widget', function () { + it('defines cookieStatus widget', function () { expect($.fn.cookieStatus).toBeDefined(); }); - it('verify that modal does not shows when cookies are supported', function () { + it('does not show a modal when cookies are supported', function () { window.navigator = { cookieEnabled: true }; From 69c07cc2e2ebfbed380148eb9b2d341ea05146d5 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 6 Feb 2020 17:31:43 +0200 Subject: [PATCH 507/666] MC-24260: Automate (convert) integration test MC-26219 --- .../Magento/CatalogImportExport/Model/Import/ProductTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 64ac63a7e3790..cb69b963cfd26 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -3046,9 +3046,7 @@ public function testEmptyAttributeValueShouldBeIgnoredAfterUpdateProductByImport $this->assertTrue($errors->getErrorsCount() === 0, 'Import file validation failed.'); $importModel->importData(); - /** @var ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); - $simpleProduct = $productRepository->get('simple', false, null, true); + $simpleProduct = $this->productRepository->get('simple', false, null, true); $this->assertEquals('Varchar default value', $simpleProduct->getData('varchar_attribute')); } } From 14112c0c79921773973a088731a7cce8a1d598da Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Thu, 6 Feb 2020 16:33:16 +0200 Subject: [PATCH 508/666] clear test data after each --- .../Magento/Theme/view/frontend/web/js/cookie-status.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js index 9b302d91d2007..67ba24fe3bcfb 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Theme/view/frontend/web/js/cookie-status.test.js @@ -1,4 +1,3 @@ - /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. @@ -16,9 +15,11 @@ define([ navigator; beforeEach(function () { - $(document.body).append(htmlContainer); widget = new Cookie(); navigator = window.navigator; + $('.modal-popup').remove(); + $('#cookie-status').remove(); + $(document.body).append(htmlContainer); }); afterEach(function () { From 5a2ea65fe45f762e9552f2d6f2786636148215fe Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 6 Feb 2020 10:46:31 -0600 Subject: [PATCH 509/666] MC-30236: Upgrade from 2.3.x CE with SD to 2.3.x EE AreaCode Exception - fix unit and integration tests --- setup/src/Magento/Setup/Model/Installer.php | 7 ++++--- .../Setup/Test/Unit/Model/InstallerTest.php | 21 +++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 2492248551461..535040f942b89 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1261,7 +1261,7 @@ public function uninstall() } /** - * Enable or disable caches for specific types + * Enable or disable caches for specific types that are available * * If no types are specified then it will enable or disable all available types * Note this is called by install() via callback. @@ -1275,9 +1275,10 @@ private function updateCaches($isEnabled, $types = []) /** @var \Magento\Framework\App\Cache\Manager $cacheManager */ $cacheManager = $this->objectManagerProvider->get()->create(\Magento\Framework\App\Cache\Manager::class); - $types = empty($types) ? $cacheManager->getAvailableTypes() : $types; + $availableTypes = $cacheManager->getAvailableTypes(); + $types = empty($types) ? $availableTypes : array_intersect($availableTypes, $types); $enabledTypes = $cacheManager->setEnabled($types, $isEnabled); - if($isEnabled){ + if ($isEnabled) { $cacheManager->clean($enabledTypes); } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index e600002d53560..7833ec127816f 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([]); $appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->disableArgumentCloning() @@ -410,15 +411,21 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [''], + [print_r([],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([],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'], From c3ba2ce2468e04ed87f11c8a2cbac7732ef1fe40 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Thu, 6 Feb 2020 23:26:35 +0530 Subject: [PATCH 510/666] improve test names --- .../app/code/Magento/Ui/base/js/grid/data-storage.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 02d303782a9d5..ade7d09797139 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 @@ -225,7 +225,7 @@ define([ expect(model.getRequest).toHaveBeenCalled(); }); - it('Return "getRequestData" method', function () { + it('it returns cached request data if a cached request exists and no refresh option is provided', function () { var params = { namespace: 'magento', search: '', @@ -247,7 +247,7 @@ define([ expect(model.getRequestData).toHaveBeenCalled(); }); - it('Return "requestData" method', function () { + it('if refresh option is true so it will ignore cache and execute the requestData function', function () { var params = { namespace: 'magento', search: '', From 4d5f03395d7d2e2da59f89bf4a0c61f9e5921b81 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Thu, 6 Feb 2020 12:13:47 -0600 Subject: [PATCH 511/666] MC-30236: Upgrade from 2.3.x CE with SD to 2.3.x EE AreaCode Exception - fix static tests --- .../Setup/Test/Unit/Model/InstallerTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index 7833ec127816f..d087162f9b06e 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -383,6 +383,7 @@ public function testInstall(array $request, array $logMessages) /** * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function installDataProvider() { @@ -411,21 +412,20 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [print_r([],true)], + [print_r([], true)], ['Installing data...'], ['Data install/update:'], ['Disabling caches:'], ['Current status:'], - [print_r([],true)], + [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)], + [print_r([], true)], ['Caches clearing:'], ['Cache cleared successfully'], ['Disabling Maintenance Mode:'], @@ -463,12 +463,12 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [print_r([],true)], + [print_r([], true)], ['Installing data...'], ['Data install/update:'], ['Disabling caches:'], ['Current status:'], - [print_r([],true)], + [print_r([], true)], ['Module \'Foo_One\':'], ['Module \'Bar_Two\':'], ['Data post-updates:'], @@ -476,7 +476,7 @@ public function installDataProvider() ['Module \'Bar_Two\':'], ['Enabling caches:'], ['Current status:'], - [print_r([],true)], + [print_r([], true)], ['Installing admin user...'], ['Caches clearing:'], ['Cache cleared successfully'], From 75b03e05c592075cf0619e419ac54d8bf62e34af Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Fri, 7 Feb 2020 08:41:55 +1030 Subject: [PATCH 512/666] #26622 - Remove unnecessary new lines and variable declaration, and make function private --- app/code/Magento/SalesRule/Model/Validator.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 8292e9c313b66..cdaac97fe6fb5 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -410,11 +410,8 @@ public function initTotals($items, Address $address) * @param Rule $rule * @return bool */ - protected function isValidItemForRule( - AbstractItem $item, - Rule $rule - ) { - /** @var AbstractItem $item */ + private function isValidItemForRule(AbstractItem $item, Rule $rule) + { if ($item->getParentItemId()) { return false; } From a037edfe8c14675a89e5e2f6839bf401ac9e253c Mon Sep 17 00:00:00 2001 From: Lachlan Turner <lachlan.turner@aligent.com.au> Date: Fri, 7 Feb 2020 08:43:05 +1030 Subject: [PATCH 513/666] #26622 - Fix return values of mock object functions --- .../SalesRule/Test/Unit/Model/ValidatorTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php index 30b198e5b9199..946963dd8d234 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php @@ -370,20 +370,20 @@ public function testInitTotalsCanApplyDiscount() $validator->expects($this->at(0))->method('isValid')->with($item1)->willReturn(false); $validator->expects($this->at(1))->method('isValid')->with($item2)->willReturn(true); - $item1->expects($this->any())->method('getParentItemId')->willReturn(false); - $item1->expects($this->any())->method('getParentItem')->willReturn(false); + $item1->expects($this->any())->method('getParentItemId')->willReturn(null); + $item1->expects($this->any())->method('getParentItem')->willReturn(null); $item1->expects($this->never())->method('getDiscountCalculationPrice'); $item1->expects($this->never())->method('getBaseDiscountCalculationPrice'); - $item2->expects($this->any())->method('getParentItemId')->willReturn(false); - $item2->expects($this->any())->method('getParentItem')->willReturn(false); + $item2->expects($this->any())->method('getParentItemId')->willReturn(null); + $item2->expects($this->any())->method('getParentItem')->willReturn(null); $item2->expects($this->any())->method('getDiscountCalculationPrice')->willReturn(50); $item2->expects($this->once())->method('getBaseDiscountCalculationPrice')->willReturn(50); - $item3->expects($this->any())->method('getParentItemId')->willReturn(false); - $item3->expects($this->any())->method('getParentItem')->willReturn(true); + $item3->expects($this->any())->method('getParentItemId')->willReturn(null); + $item3->expects($this->any())->method('getParentItem')->willReturn($item1); $item3->expects($this->never())->method('getDiscountCalculationPrice'); $item3->expects($this->never())->method('getBaseDiscountCalculationPrice'); - $item4->expects($this->any())->method('getParentItemId')->willReturn(true); - $item4->expects($this->any())->method('getParentItem')->willReturn(false); + $item4->expects($this->any())->method('getParentItemId')->willReturn(12345); + $item4->expects($this->any())->method('getParentItem')->willReturn(null); $item4->expects($this->never())->method('getDiscountCalculationPrice'); $item4->expects($this->never())->method('getBaseDiscountCalculationPrice'); $this->utility->expects($this->once())->method('getItemQty')->willReturn(1); From bfeadd7e3971a278784155cfddefc80c7aeeb07d Mon Sep 17 00:00:00 2001 From: Alex Lukyanau <cybergomel@gmail.com> Date: Thu, 6 Feb 2020 17:15:32 -0500 Subject: [PATCH 514/666] Removed Magento/Customer/Model/RedirectCookieManager. Deprecated getCookieManager, setCookieManager, getRedirectCookie, setRedirectCookie, clearRedirectCookie --- .../Customer/Model/Account/Redirect.php | 47 ++++++----- .../Customer/Model/RedirectCookieManager.php | 81 ------------------- .../Test/Unit/Model/Account/RedirectTest.php | 10 +-- 3 files changed, 30 insertions(+), 108 deletions(-) delete mode 100755 app/code/Magento/Customer/Model/RedirectCookieManager.php diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index e0e5730c4281b..583f25dbf95c9 100755 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -20,7 +20,6 @@ use Magento\Framework\Url\DecoderInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Stdlib\CookieManagerInterface; -use Magento\Customer\Model\RedirectCookieManager; /** * Account Redirect @@ -29,10 +28,7 @@ */ class Redirect { - /** @deprecated - * @see \Magento\Customer\Model\RedirectCookieManager - * URL to redirect user on successful login or registration - */ + /** URL to redirect user on successful login or registration */ const LOGIN_REDIRECT_URL = 'login_redirect'; /** @@ -72,14 +68,9 @@ class Redirect protected $resultFactory; /** - * @var CookieManagerInterface - */ - protected $cookieManager; - - /** - * @var RedirectCookieManager + * @var CookieMetadataFactory */ - protected $redirectCookieManager; + protected $cookieMetadataFactory; /** * @var HostChecker @@ -101,7 +92,7 @@ class Redirect * @param DecoderInterface $urlDecoder * @param CustomerUrl $customerUrl * @param ResultFactory $resultFactory - * @param RedirectCookieManager $redirectCookieManager + * @param CookieMetadataFactory $cookieMetadataFactory * @param HostChecker|null $hostChecker */ public function __construct( @@ -113,7 +104,7 @@ public function __construct( DecoderInterface $urlDecoder, CustomerUrl $customerUrl, ResultFactory $resultFactory, - RedirectCookieManager $redirectCookieManager, + CookieMetadataFactory $cookieMetadataFactory HostChecker $hostChecker = null ) { $this->request = $request; @@ -123,8 +114,8 @@ public function __construct( $this->url = $url; $this->urlDecoder = $urlDecoder; $this->customerUrl = $customerUrl; + $this->cookieMetadataFactory = $cookieMetadataFactory; $this->resultFactory = $resultFactory; - $this->redirectCookieManager = $redirectCookieManager; $this->hostChecker = $hostChecker ?: ObjectManager::getInstance()->get(HostChecker::class); } @@ -254,8 +245,8 @@ private function applyRedirect($url) /** * Get Cookie manager. For release backward compatibility. * - * @deprecated 100.0.10 - * @see \Magento\Customer\Model\RedirectCookieManager + * @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() @@ -269,8 +260,8 @@ protected function getCookieManager() /** * Set cookie manager. For unit tests. * - * @deprecated 100.0.10 - * @see \Magento\Customer\Model\RedirectCookieManager + * @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 */ @@ -282,31 +273,43 @@ 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() { - return $this->redirectCookieManager->getRedirectCookie(); + return $this->getCookieManager()->getCookie(self::LOGIN_REDIRECT_URL, null); } /** * 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->redirectCookieManager->setRedirectCookie($route, $this->storeManager->getStore()); + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setHttpOnly(true) + ->setDuration(3600) + ->setPath($this->storeManager->getStore()->getStorePath()); + $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route, $cookieMetadata); } /** * 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->redirectCookieManager->clearRedirectCookie($this->storeManager->getStore()); + $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setPath($this->storeManager->getStore()->getStorePath()); + $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL, $cookieMetadata); } } diff --git a/app/code/Magento/Customer/Model/RedirectCookieManager.php b/app/code/Magento/Customer/Model/RedirectCookieManager.php deleted file mode 100755 index 27a6be6671f30..0000000000000 --- a/app/code/Magento/Customer/Model/RedirectCookieManager.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Customer\Model; - -use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; -use Magento\Framework\Stdlib\CookieManagerInterface; -use Magento\Store\Api\Data\StoreInterface; - -/** - * Customer redirect cookie manager - * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) - */ -class RedirectCookieManager -{ - const COOKIE_NAME = 'login_redirect'; - - /** - * @var CookieMetadataFactory - */ - private $cookieMetadataFactory; - - /** - * @var CookieManagerInterface - */ - private $cookieManager; - - /** - * @param CookieMetadataFactory $cookieMetadataFactory - * @param CookieManagerInterface $cookieManager - */ - public function __construct( - CookieMetadataFactory $cookieMetadataFactory, - CookieManagerInterface $cookieManager - ) { - $this->cookieMetadataFactory = $cookieMetadataFactory; - $this->cookieManager = $cookieManager; - } - - /** - * Get redirect route from cookie for case of successful login/registration - * - * @return null|string - */ - public function getRedirectCookie() - { - return $this->cookieManager->getCookie(self::COOKIE_NAME, null); - } - - /** - * Save redirect route to cookie for case of successful login/registration - * - * @param string $route - * @param StoreInterface $store - * @return void - */ - public function setRedirectCookie($route, StoreInterface $store) - { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setHttpOnly(true) - ->setDuration(3600) - ->setPath($store->getStorePath()); - $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $route, $cookieMetadata); - } - - /** - * Clear cookie with requested route - * - * @param StoreInterface $store - * @return void - */ - public function clearRedirectCookie(StoreInterface $store) - { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setPath($store->getStorePath()); - $this->cookieManager->deleteCookie(self::COOKIE_NAME, $cookieMetadata); - } -} 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 5efef491adae1..f520182e51199 100755 --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -8,7 +8,7 @@ namespace Magento\Customer\Test\Unit\Model\Account; -use Magento\Customer\Model\RedirectCookieManager; +use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; use Magento\Customer\Model\Account\Redirect; use Magento\Customer\Model\Url as CustomerUrl; use Magento\Framework\Controller\ResultFactory; @@ -82,9 +82,9 @@ class RedirectTest extends \PHPUnit\Framework\TestCase protected $resultFactory; /** - * @var RedirectCookieManager | \PHPUnit_Framework_MockObject_MockObject + * @var CookieMetadataFactory | \PHPUnit_Framework_MockObject_MockObject */ - protected $redirectCookieManager; + protected $cookieMetadataFactory; /** * @var HostChecker | \PHPUnit_Framework_MockObject_MockObject @@ -147,7 +147,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->redirectCookieManager = $this->getMockBuilder(RedirectCookieManager::class) + $this->cookieMetadataFactory = $this->getMockBuilder(CookieMetadataFactory::class) ->disableOriginalConstructor() ->getMock(); @@ -167,7 +167,7 @@ protected function setUp() 'urlDecoder' => $this->urlDecoder, 'customerUrl' => $this->customerUrl, 'resultFactory' => $this->resultFactory, - 'redirectCookieManager' => $this->redirectCookieManager, + 'cookieMetadataFactory' => $this->cookieMetadataFactory, 'hostChecker' => $this->hostChecker, ] ); From dc416a9bb545517384bff75c1bc1e181a1343af0 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau <cybergomel@gmail.com> Date: Thu, 6 Feb 2020 17:38:03 -0500 Subject: [PATCH 515/666] Removed Magento/Customer/Model/RedirectCookieManager. Deprecated getCookieManager, setCookieManager, getRedirectCookie, setRedirectCookie, clearRedirectCookie --- app/code/Magento/Customer/Model/Account/Redirect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index ebc2091410489..0d2cbdf6a6051 100755 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -105,7 +105,7 @@ public function __construct( DecoderInterface $urlDecoder, CustomerUrl $customerUrl, ResultFactory $resultFactory, - CookieMetadataFactory $cookieMetadataFactory + CookieMetadataFactory $cookieMetadataFactory, HostChecker $hostChecker = null ) { $this->request = $request; From 41ce59e5f53564e9e665660ccee618a390ca1de3 Mon Sep 17 00:00:00 2001 From: Alex Lukyanau <cybergomel@gmail.com> Date: Thu, 6 Feb 2020 18:21:09 -0500 Subject: [PATCH 516/666] Removed Magento/Customer/Model/RedirectCookieManager. Deprecated getCookieManager, setCookieManager, getRedirectCookie, setRedirectCookie, clearRedirectCookie --- app/code/Magento/Customer/Model/Account/Redirect.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php index 0d2cbdf6a6051..ba1f72369f606 100755 --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -73,6 +73,11 @@ class Redirect */ protected $cookieMetadataFactory; + /** + * @var CookieManagerInterface + */ + private $cookieManager; + /** * @var HostChecker */ From eeaadb82cea7c7d32e42ad434496eb124bc504f3 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Fri, 7 Feb 2020 10:40:11 +0200 Subject: [PATCH 517/666] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...tProductPriceInCategoryPageActionGroup.xml | 26 ++++++ ...tSpecialPriceInCategoryPageActionGroup.xml | 21 +++++ .../StorefrontCategoryProductSection.xml | 2 +- ...hipArePersistedUnderLongTermCookieTest.xml | 90 +++++++++++-------- ...AssertDefaultWelcomeMessageActionGroup.xml | 20 +++++ .../StorefrontCustomerLogoutActionGroup.xml | 4 +- 6 files changed, 124 insertions(+), 39 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml 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..e6eb475153f1f --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.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="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> + + <!-- Go to storefront category page, assert product visibility --> + <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..17c9e43e15fa7 --- /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 is present and 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/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 4114d64eb39af..9ee019c9e934e 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="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@data-price-type='finalPrice']/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/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 86d3dccba7595..9bae928c66426 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -15,71 +15,89 @@ <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> - <actionGroup ref="LoginAsAdmin" stepKey="login"/> + <!--Delete all Catalog Price Rule if exist--> + <actionGroup ref="LoginAsAdmin" stepKey="loginToAdminPanel"/> + <actionGroup ref="AdminCatalogPriceRuleDeleteAllActionGroup" stepKey="deleteAllCatalogPriceRule"/> + + <!--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="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="AdminFillCatalogRuleConditionActionGroup" stepKey="createCatalogPriceRule"> + <argument name="conditionValue" value="$createCategory.id$"/> + </actionGroup> + <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="logout" 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="AssertDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> + <actionGroup ref="AssertStorefrontProductPriceInCategoryPageActionGroup" stepKey="assertProductPriceInCategoryPageAfterLogout"> + <argument name="categoryUrl" value="$createCategory.custom_attributes[url_key]$"/> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml new file mode 100644 index 0000000000000..05414fb8ebe20 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.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="AssertDefaultWelcomeMessageActionGroup"> + <annotations> + <description>Validates that the Welcome message is present and correct and not you link absent.</description> + </annotations> + + <waitForPageLoad stepKey="waitForPageLoad"/> + <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/StorefrontCustomerLogoutActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml index ed221350918a0..98a7f4c8d1544 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLogoutActionGroup.xml @@ -24,7 +24,7 @@ <click selector="{{StoreFrontSignOutSection.customerAccount}}" stepKey="clickCustomerButton"/> <click selector="{{StoreFrontSignOutSection.signOut}}" stepKey="clickToSignOut"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <see userInput="You are signed out" stepKey="signOut"/> + <waitForText selector="{{StorefrontCMSPageSection.mainTitle}}" userInput="You are signed out" stepKey="signOut"/> + <waitForText selector="{{StorefrontCMSPageSection.mainTitle}}" userInput="Home Page" stepKey="waitForHomePageLoad"/> </actionGroup> </actionGroups> From ea007205d88951a93d4ba1fc6365a3b0858af6a6 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 7 Feb 2020 10:54:08 +0200 Subject: [PATCH 518/666] Add return type assertion --- .../Test/Unit/Observer/ResetAttemptForBackendObserverTest.php | 4 ++-- .../Unit/Observer/ResetAttemptForFrontendObserverTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php index b7a0c9534598d..b984daa8998f3 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForBackendObserverTest.php @@ -28,7 +28,7 @@ class ResetAttemptForBackendObserverTest extends TestCase public function testExecuteExpectsDeleteUserAttemptsCalled() { $logMock = $this->createMock(Log::class); - $logMock->expects($this->once())->method('deleteUserAttempts'); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); $resLogFactoryMock = $this->createMock(LogFactory::class); $resLogFactoryMock->expects($this->once()) @@ -48,6 +48,6 @@ public function testExecuteExpectsDeleteUserAttemptsCalled() ResetAttemptForBackendObserver::class, ['resLogFactory' => $resLogFactoryMock] ); - $observer->execute($eventObserverMock); + $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 index f83341eb8680d..11866c266845e 100644 --- a/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php +++ b/app/code/Magento/Captcha/Test/Unit/Observer/ResetAttemptForFrontendObserverTest.php @@ -28,7 +28,7 @@ class ResetAttemptForFrontendObserverTest extends TestCase public function testExecuteExpectsDeleteUserAttemptsCalled() { $logMock = $this->createMock(Log::class); - $logMock->expects($this->once())->method('deleteUserAttempts'); + $logMock->expects($this->once())->method('deleteUserAttempts')->willReturnSelf(); $resLogFactoryMock = $this->createMock(LogFactory::class); $resLogFactoryMock->expects($this->once()) @@ -47,6 +47,6 @@ public function testExecuteExpectsDeleteUserAttemptsCalled() ResetAttemptForFrontendObserver::class, ['resLogFactory' => $resLogFactoryMock] ); - $observer->execute($eventObserverMock); + $this->assertInstanceOf(Log::class, $observer->execute($eventObserverMock)); } } From 3f1789cefb3637ed90c93af8e2dd4bffe34e523d Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 7 Feb 2020 11:29:41 +0200 Subject: [PATCH 519/666] MC-30384: [2.4] Test StorefrontInactiveCatalogRuleTest fails on Jenkins (MC-79) --- .../Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index 32cdb4869ddde..45b0c1bcaa5a0 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -59,8 +59,6 @@ <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage"> <argument name="productName" value="$createProduct.name$"/> </actionGroup> - <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart"/> - <actionGroup ref="StorefrontOpenCartPageActionGroup" stepKey="openCartPage" /> <waitForElementVisible selector="{{CheckoutCartSummarySection.subtotal}}" stepKey="waitForSubtotalAppears"/> <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$createProduct.price$" stepKey="seeProductPriceOnCartPage"/> From aadf200156c5e56907d76efceb892dca18a1d389 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 7 Feb 2020 12:07:15 +0200 Subject: [PATCH 520/666] fix changes requested --- .../Ui/TemplateEngine/Xhtml/Result.php | 23 +++++++++---------- .../Unit/TemplateEngine/Xhtml/ResultTest.php | 8 +++---- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php index 1fb79ce6d7653..d15f94bd6f2dd 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -5,18 +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; /** - * @inheritdoc + * Convert DOMElement to string representation */ class Result implements ResultInterface { @@ -61,8 +60,8 @@ class Result implements ResultInterface * @param UiComponentInterface $component * @param Structure $structure * @param LoggerInterface $logger - * @param JsonHexTag|null $jsonSerializer - * @param State|null $state + * @param JsonHexTag $jsonSerializer + * @param State $state */ public function __construct( Template $template, @@ -70,16 +69,16 @@ public function __construct( UiComponentInterface $component, Structure $structure, LoggerInterface $logger, - ?JsonHexTag $jsonSerializer = null, - ?State $state = 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->state = $state ?? ObjectManager::getInstance()->get(State::class); + $this->jsonSerializer = $jsonSerializer; + $this->state = $state; } /** @@ -128,7 +127,7 @@ public function __toString() $this->logger->critical($e); $result = $e->getMessage(); if ($this->state->getMode() === State::MODE_DEVELOPER) { - $result .= "<pre><code>{$e->__toString()}</code></pre>"; + $result .= "<pre><code>Exception in {$e->getFile()}:{$e->getLine()}</code></pre>"; } } return $result; diff --git a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php index 5f73fa8f0fcd3..b2623bfb5c7c5 100644 --- a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -111,20 +111,20 @@ protected function setUp() */ public function testToStringWithException(): void { - $exception = new \Exception(); + $e = new \Exception(); $this->templateMock->expects($this->once()) ->method('getDocumentElement') - ->willThrowException($exception); + ->willThrowException($e); $this->stateMock->expects($this->once()) ->method('getMode') ->willReturn(State::MODE_DEVELOPER); $this->loggerMock->expects($this->once()) ->method('critical') - ->with($exception); + ->with($e); $this->assertEquals( - '<pre><code>' . $exception->__toString() . '</code></pre>', + '<pre><code>Exception in ' . $e->getFile() . ':' . $e->getLine() . '</code></pre>', $this->model->__toString() ); } From 8e0d7ba31112e129a789750ad90ec574ab02c355 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 7 Feb 2020 12:24:08 +0200 Subject: [PATCH 521/666] Fix return type in ResetAttemptForFrontendObserver and ResetAttemptForBackendObserver classes. code cleaning --- .../ResetAttemptForBackendObserver.php | 20 +++++++++++----- .../ResetAttemptForFrontendObserver.php | 23 +++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) 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()); From 9d992d0cf9cf594f892422a5522fd7c83486784a Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 12:30:48 +0200 Subject: [PATCH 522/666] refactoring, static test fixes --- .../Grid/Column/Renderer/AbstractRenderer.php | 6 +++- .../Gateway/Data/PaymentDataObjectTest.php | 34 ++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) 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 c58bcdf5108cb..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) { @@ -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/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php index e816533d59088..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,45 +5,61 @@ */ 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()); } - public function testGetPayment() + /** + * Verify can get payment + * + * @return void + */ + public function testGetPayment(): void { $this->assertSame($this->paymentMock, $this->model->getPayment()); } From d31e71164f5a6efe33b7f0cee3be74bdbd9b3386 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 7 Feb 2020 12:44:20 +0200 Subject: [PATCH 523/666] fix changes requested --- .../Unit/TemplateEngine/Xhtml/ResultTest.php | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php index b2623bfb5c7c5..0890a3c095c40 100644 --- a/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php +++ b/app/code/Magento/Ui/Test/Unit/TemplateEngine/Xhtml/ResultTest.php @@ -4,13 +4,13 @@ * 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\Serialize\Serializer\JsonHexTag; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Framework\View\Layout\Generator\Structure; use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; use Magento\Framework\View\TemplateEngine\Xhtml\Template; use Magento\Ui\Component\Listing; @@ -21,8 +21,6 @@ /** * Test for \Magento\Ui\TemplateEngine\Xhtml\Result. - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ResultTest extends TestCase { @@ -56,21 +54,11 @@ class ResultTest extends TestCase */ private $componentMock; - /** - * @var Structure|MockObject - */ - private $structureMock; - /** * @var LoggerInterface|MockObject */ private $loggerMock; - /** - * @var JsonHexTag|MockObject - */ - private $jsonSerializerMock; - /** * @var State|MockObject */ @@ -84,10 +72,8 @@ protected function setUp() $this->templateMock = $this->createMock(Template::class); $this->compilerMock = $this->createMock(CompilerInterface::class); $this->componentMock = $this->createMock(Listing::class); - $this->structureMock = $this->createMock(Structure::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->stateMock = $this->createMock(State::class); - $this->jsonSerializerMock = $this->createMock(JsonHexTag::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->model = $this->objectManagerHelper->getObject( @@ -96,9 +82,7 @@ protected function setUp() 'template' => $this->templateMock, 'compiler' => $this->compilerMock, 'component' => $this->componentMock, - 'structure' => $this->structureMock, 'logger' => $this->loggerMock, - 'jsonSerializer' => $this->jsonSerializerMock, 'state' => $this->stateMock, ] ); From 86b6f19371f7d2a8fd475cdc029cfd5fe070e889 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 7 Feb 2020 13:09:03 +0200 Subject: [PATCH 524/666] MC-24260: Automate (convert) integration test MC-26219 --- .../_files/product_with_varchar_attribute.php | 19 ++++++------------- .../Model/Import/ProductTest.php | 3 ++- 2 files changed, 8 insertions(+), 14 deletions(-) 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 index 7cc6b9fac4fe1..e2a5f560c8b7b 100644 --- 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 @@ -5,24 +5,17 @@ */ declare(strict_types=1); -use Magento\Catalog\Api\Data\ProductAttributeInterface; -use Magento\Catalog\Api\Data\ProductInterface; use Magento\Eav\Model\Config; require __DIR__ . '/product_varchar_attribute.php'; require __DIR__ . '/product_simple.php'; /** @var Config $eavConfig */ -$eavConfig = $objectManager->create(Config::class); - -$attributeCode = 'varchar_attribute'; -/** @var ProductAttributeInterface $varcharAttribute */ -$varcharAttribute = $attributeRepository->get($attributeCode); -$varcharAttribute->setDefaultValue('Varchar default value'); -$attributeRepository->save($varcharAttribute); +$eavConfig = $objectManager->get(Config::class); $eavConfig->clear(); -/** @var ProductInterface $simpleProduct */ -$simpleProduct = $productRepository->get('simple'); -$simpleProduct->setCustomAttribute($attributeCode, $attributeRepository->get($attributeCode)->getDefaultValue()); -$productRepository->save($simpleProduct); +$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/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index cb69b963cfd26..6f990ca06f0eb 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -3038,7 +3038,8 @@ public function testProductStockStatusShouldBeUpdatedOnSchedule() */ public function testEmptyAttributeValueShouldBeIgnoredAfterUpdateProductByImport() { - $pathToFile = __DIR__ . '/_files/' . 'import_product_with_empty_attribute_value.csv'; + $pathToFile = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR + . 'import_product_with_empty_attribute_value.csv'; /** @var ImportProduct $importModel */ $importModel = $this->createImportModel($pathToFile); /** @var ProcessingErrorAggregatorInterface $errors */ From 7b99e510a4feaa5fdde059e4e87668a43e3d348c Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:18:40 +0200 Subject: [PATCH 525/666] reafactoring, declare empty array variable --- app/code/Magento/Search/Block/Term.php | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 6dab372df3edc..5df68c240ddce 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 */ @@ -71,17 +75,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 +95,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; @@ -112,8 +117,10 @@ protected function _loadTerms() } /** + * Load and return terms + * * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ public function getTerms() { @@ -122,10 +129,12 @@ public function getTerms() } /** - * @param \Magento\Framework\DataObject $obj + * Return search url + * + * @param DataObject $obj * @return string */ - public function getSearchUrl($obj) + public function getSearchUrl(DataObject $obj) { /** @var $url UrlInterface */ $url = $this->_urlFactory->create(); @@ -138,6 +147,8 @@ public function getSearchUrl($obj) } /** + * Return max popularity + * * @return int */ public function getMaxPopularity() @@ -146,6 +157,8 @@ public function getMaxPopularity() } /** + * Return min popularity + * * @return int */ public function getMinPopularity() From c58a7e3b74e61064988326a344252f52eb4c11bb Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:21:02 +0200 Subject: [PATCH 526/666] small improvements --- app/code/Magento/Search/Block/Term.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 5df68c240ddce..69d180f79e680 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -41,15 +41,11 @@ class Term extends Template protected $_maxPopularity; /** - * Url factory - * * @var UrlFactory */ protected $_urlFactory; /** - * Query collection factory - * * @var CollectionFactory */ protected $_queryCollectionFactory; From 1e14f000e8b32a6a0a1101879b5632af1f733cfb Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 13:51:51 +0200 Subject: [PATCH 527/666] revert param type --- app/code/Magento/Search/Block/Term.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 69d180f79e680..9010e3e1dbbc1 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -130,7 +130,7 @@ public function getTerms() * @param DataObject $obj * @return string */ - public function getSearchUrl(DataObject $obj) + public function getSearchUrl($obj) { /** @var $url UrlInterface */ $url = $this->_urlFactory->create(); From 42d0c1a979ffc23d885b7ba074fb8221d21c9b20 Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" <ivan.pletnyov@transoftgroup.com> Date: Fri, 7 Feb 2020 14:04:39 +0200 Subject: [PATCH 528/666] MC-31256: Admin: Create/update/delete customer addresses --- .../Directory/Model/GetRegionIdByName.php | 54 +++ .../Model/Address/CreateAddressTest.php | 368 ++++++++++++++++++ .../Model/Address/DeleteAddressTest.php | 92 +++++ .../Model/Address/UpdateAddressTest.php | 294 ++++++++++++++ .../_files/customer_no_address_rollback.php | 30 ++ 5 files changed, 838 insertions(+) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Directory/Model/GetRegionIdByName.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/customer_no_address_rollback.php 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/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php new file mode 100644 index 0000000000000..ae65c32fe3f43 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -0,0 +1,368 @@ +<?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 + */ + private $objectManager; + + /** + * @var GetRegionIdByName + */ + private $getRegionIdByName; + + /** + * @var AddressInterfaceFactory + */ + private $addressFactory; + + /** + * @var AddressRegistry + */ + private $addressRegistry; + + /** + * @var Address + */ + private $addressResource; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var int[] + */ + private $createdAddressesIds = []; + + /** + * @inheritdoc + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->getRegionIdByName = $this->objectManager->get(GetRegionIdByName::class); + $this->addressFactory = $this->objectManager->get(AddressInterfaceFactory::class); + $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->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_string' => [ + array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => '']), + InputException::requiredField('street'), + ], + '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 + */ + private 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..fe5437e294fc6 --- /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 + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $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..8867f269cdf37 --- /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 + */ + private $addressRegistry; + + /** + * @var Address + */ + private $addressResource; + + /** + * @var CustomerRegistry + */ + private $customerRegistry; + + /** + * @var AddressRepositoryInterface + */ + private $addressRepository; + + /** + * @var CustomerRepositoryInterface + */ + private $customerRepository; + + /** + * @var int[] + */ + private $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/_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); From 63815dbdfe955e71ae6490e3bd993250e17e1d84 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 7 Feb 2020 15:20:15 +0200 Subject: [PATCH 529/666] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- ...minDeleteProductAttributeByLabelActionGroup.xml | 12 ++++++------ .../Mftf/Data/AdminProductAttributeMessageData.xml | 14 ++++++++++++++ .../Test/Mftf/Test/AdminCreateImageSwatchTest.xml | 9 +++------ 3 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/AdminProductAttributeMessageData.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml index 7898fae279eaf..21cc90ba4b4e8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -13,19 +13,19 @@ <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"/> + <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="{{ModalConfirmationSection.modalContent}}" stepKey="waitForConfirmationPopUpVisible"/> - <click selector="{{ModalConfirmationSection.OkButton}}" stepKey="clickOnConfirmationButton"/> - <waitForPageLoad stepKey="waitForAttributeGridPageLoad"/> - <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" stepKey="waitForSuccessMessageVisible"/> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="You deleted the product attribute." stepKey="seeAttributeDeleteSuccessMessage"/> + <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/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/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 34eaa2f34ba17..372df5bd3acee 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -30,6 +30,7 @@ <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"> <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> </actionGroup> + <actionGroup ref="NavigateToAndResetProductAttributeGridToDefaultViewActionGroup" stepKey="resetProductAttributeFilters"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> @@ -102,11 +103,7 @@ </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> @@ -150,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 --> From 05ac25997d5fa5f7a7e446c18d1c361dbe629988 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 7 Feb 2020 15:23:28 +0200 Subject: [PATCH 530/666] MC-31128: Refund Offline button is disabled because of JS error --- .../Test/Mftf/ActionGroup/SubmitCreditMemoActionGroup.xml | 4 ++-- .../Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/SubmitCreditMemoActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/SubmitCreditMemoActionGroup.xml index fbd2a0047d558..2605adbfc91a7 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/SubmitCreditMemoActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/SubmitCreditMemoActionGroup.xml @@ -10,8 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SubmitCreditMemoActionGroup"> <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> - <waitForElementVisible selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="waitButtonEnabled"/> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickSubmitCreditMemo"/> + <waitForElementVisible selector="{{AdminCreditMemoTotalSection.submitRefundOfflineEnabled}}" stepKey="waitButtonEnabled"/> + <click selector="{{AdminCreditMemoTotalSection.submitRefundOfflineEnabled}}" stepKey="clickSubmitCreditMemo"/> <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForMessageAppears"/> <see selector="{{AdminMessagesSection.success}}" userInput="You created the credit memo." stepKey="seeCreditMemoCreateSuccess"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}$grabOrderId" stepKey="seeViewOrderPageCreditMemo"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml index 6b4bdf69361a5..8efd373f54543 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminCreditMemoTotalSection.xml @@ -19,6 +19,7 @@ <element name="emailCopy" type="checkbox" selector=".order-totals-actions #send_email"/> <element name="refundStoreCredit" type="checkbox" selector=".order-totals-actions .field-refund-store-credit input[type='checkbox']"/> <element name="submitRefundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']" timeout="30"/> + <element name="submitRefundOfflineEnabled" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-button']:not(.disabled)" timeout="60"/> <element name="creditMemoItem" type="text" selector="#sales_order_view_tabs_order_creditmemos"/> <element name="viewMemo" type="text" selector="div#sales_order_view_tabs_order_creditmemos_content a.action-menu-item"/> <element name="refundOffline" type="button" selector=".order-totals-actions button[data-ui-id='order-items-submit-offline']"/> From 17600435ec7aed34dc93fcbda71f3bf8a2e1db09 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 15:37:28 +0200 Subject: [PATCH 531/666] cover changes with unit test --- .../Search/Test/Unit/Block/TermsTest.php | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 app/code/Magento/Search/Test/Unit/Block/TermsTest.php 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 + ] + ]; + } +} From d1f1ebaf34dab66e16acf52a4a0b135282399d1c Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 7 Feb 2020 15:42:35 +0200 Subject: [PATCH 532/666] remove unesscesary check --- app/code/Magento/Search/Block/Term.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Search/Block/Term.php b/app/code/Magento/Search/Block/Term.php index 9010e3e1dbbc1..ed6a2c5215b54 100644 --- a/app/code/Magento/Search/Block/Term.php +++ b/app/code/Magento/Search/Block/Term.php @@ -100,9 +100,7 @@ protected function _loadTerms() $temp[$term->getQueryText()] = $term; $termKeys[] = $term->getQueryText(); } - if (empty($termKeys)) { - return $this; - } + natcasesort($termKeys); foreach ($termKeys as $termKey) { From aa344a181a41439623f5f9021052a1ac0b6c4750 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Fri, 7 Feb 2020 15:44:20 +0200 Subject: [PATCH 533/666] MC-31267: Storefront: Check bundle product regular price --- .../View/Type/BundleProductPriceTest.php | 172 ++++++++++++++++++ ...amic_bundle_product_multiselect_option.php | 97 ++++++++++ ...le_product_multiselect_option_rollback.php | 22 +++ .../Bundle/_files/multiple_products.php | 116 ++++++------ 4 files changed, 351 insertions(+), 56 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/BundleProductPriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_multiselect_option_rollback.php 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/_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/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); From 0a816b9ae0395ba3706a2a9410ade663a779ad7c Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Fri, 7 Feb 2020 15:57:48 +0200 Subject: [PATCH 534/666] MC-31260: Storefront: Create/update customer --- .../AccountManagement/CreateAccountTest.php | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/CreateAccountTest.php 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; + } +} From dec34b35139d773c24a59d3cfbe3e9786c30659e Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Fri, 7 Feb 2020 16:01:59 +0200 Subject: [PATCH 535/666] MC-31269: Admin: Add/edit/delete custom options to configurable product --- .../Product/Save/CreateCustomOptionsTest.php | 10 ++++--- .../Product/Save/DeleteCustomOptionsTest.php | 10 ++++--- .../Product/Save/UpdateCustomOptionsTest.php | 10 ++++--- .../Product/Save/CreateCustomOptionsTest.php | 26 +++++++++++++++++++ .../Product/Save/DeleteCustomOptionsTest.php | 26 +++++++++++++++++++ .../Product/Save/UpdateCustomOptionsTest.php | 26 +++++++++++++++++++ 6 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/CreateCustomOptionsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/DeleteCustomOptionsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Save/UpdateCustomOptionsTest.php 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/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'; +} From 4ff98439037e473340b7e31c340b3cf373aa0b71 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Fri, 7 Feb 2020 16:14:32 +0200 Subject: [PATCH 536/666] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- .../Test/Mftf/Section/StorefrontCategoryProductSection.xml | 2 +- ...stomerGroupMembershipArePersistedUnderLongTermCookieTest.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 9ee019c9e934e..12fd350612d7d 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="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@data-price-type='finalPrice']/span" parameterized="true"/> + <element name="ProductCatalogRuleSpecialPriceTitleByName" type="text" selector="//main//li[.//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/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 9bae928c66426..65a0e30e17b37 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -99,5 +99,6 @@ <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> From 9b585ee2963994a56c4ca35fd80c8cb6d5c7fd44 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Fri, 7 Feb 2020 17:13:24 +0200 Subject: [PATCH 537/666] MC-30650: [Magento Cloud] Customer Creation - The store view is not in the associated website --- .../Test/CheckTierPricingOfProductsTest.xml | 2 + .../Controller/Adminhtml/Index/Save.php | 8 +- .../Customer/Model/AccountManagement.php | 24 +- .../Controller/Adminhtml/Index/SaveTest.php | 5 +- .../Test/Unit/Model/AccountManagementTest.php | 161 +++++++------- .../Unit/ViewModel/Customer/StoreTest.php | 210 ++++++++++++++++++ .../Customer/ViewModel/Customer/Store.php | 131 +++++++++++ .../view/base/ui_component/customer_form.xml | 8 +- .../web/js/lib/knockout/bindings/optgroup.js | 2 +- 9 files changed, 460 insertions(+), 91 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/ViewModel/Customer/StoreTest.php create mode 100644 app/code/Magento/Customer/ViewModel/Customer/Store.php diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 4e0e8d03f59d5..f80cfed54c8f3 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,6 +329,7 @@ <actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="DeleteWebsite"> <argument name="websiteName" value="secondWebsite"/> </actionGroup> + <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> <actionGroup ref="logout" stepKey="logout"/> <!--Do reindex and flush cache--> 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/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 55da6a62f0625..e2d997ed445b8 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); } @@ -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. * 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/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 3c38cd0f7b4e2..2344e0c8bce02 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') @@ -1810,62 +1794,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 +1989,6 @@ private function prepareDateTimeFactory() public function testCreateAccountUnexpectedValueException(): void { $websiteId = 1; - $storeId = null; $defaultStoreId = 1; $customerId = 1; $customerEmail = 'email@email.com'; @@ -2048,8 +2006,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 +2021,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 +2037,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 +2118,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/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/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/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) From 6e4a0410ada941c681310f480c788ed4b309b11b Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Fri, 7 Feb 2020 17:14:44 +0200 Subject: [PATCH 538/666] Cover MFTF test --- ...WithCustomOptionFileToOrderActionGroup.xml | 24 +++++++++ ...minChangeCustomerOptionFileActionGroup.xml | 26 ++++++++++ .../Test/Mftf/Page/AdminOrderCreatePage.xml | 1 + .../AdminOrderFormCustomOptionsSection.xml | 16 ++++++ ...rWithSimpleProductCustomOptionFileTest.xml | 52 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAddSimpleProductWithCustomOptionFileToOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminChangeCustomerOptionFileActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormCustomOptionsSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml 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/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/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/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/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderWithSimpleProductCustomOptionFileTest.xml new file mode 100644 index 0000000000000..200ac6e62ac15 --- /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="logout" 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> From f7988a877f24ccb97473dd905d45cf4b5f3c1fcd Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Fri, 7 Feb 2020 17:58:29 +0200 Subject: [PATCH 539/666] Unit tests for Magento\Csp\Model\Mode\ConfigManager and Magento\Csp\Observer\Render --- .../Unit/Model/Mode/ConfigManagerTest.php | 127 ++++++++++++++++++ .../Csp/Test/Unit/Observer/RenderTest.php | 52 +++++++ 2 files changed, 179 insertions(+) create mode 100644 app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php create mode 100644 app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php diff --git a/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php new file mode 100644 index 0000000000000..8e47641c46b89 --- /dev/null +++ b/app/code/Magento/Csp/Test/Unit/Model/Mode/ConfigManagerTest.php @@ -0,0 +1,127 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Csp\Test\Unit\Model\Mode; + +use Magento\Csp\Model\Mode\ConfigManager; +use Magento\Csp\Model\Mode\Data\ModeConfigured; +use Magento\Framework\App\Area; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\State; +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\Csp\Model\Mode\ConfigManager + */ +class ConfigManagerTest extends TestCase +{ + const STUB_REPORT_ONLY = true; + const STUB_AREA_CODE_OTHER = 'other'; + + /** + * @var MockObject|ScopeConfigInterface + */ + private $configMock; + + /** + * @var MockObject|Store + */ + private $storeModelMock; + + /** + * @var MockObject|State + */ + private $stateMock; + + /** + * @var ConfigManager + */ + private $model; + + /** + * @inheritDoc + */ + protected function setUp() + { + $this->configMock = $this->createMock(ScopeConfigInterface::class); + $this->storeModelMock = $this->createMock(Store::class); + $this->stateMock = $this->createMock(State::class); + + $objectManagerHelper = new ObjectManagerHelper($this); + $this->model = $objectManagerHelper->getObject( + ConfigManager::class, + [ + 'config' => $this->configMock, + 'storeModel' => $this->storeModelMock, + 'state' => $this->stateMock + ] + ); + } + + /** + * Test case with correct Area codes. + * + * @param string $area + * @param string $pathReportOnly + * @param string $pathReportUri + * @dataProvider dataProviderGetConfiguredWithCorrectArea + */ + public function testGetConfiguredWithCorrectArea(string $area, string $pathReportOnly, string $pathReportUri) + { + $this->stateMock->expects($this->once())->method('getAreaCode')->willReturn($area); + + $this->configMock->expects($this->once())->method('getValue')->with($pathReportUri); + $this->configMock->expects($this->once()) + ->method('isSetFlag') + ->with($pathReportOnly) + ->willReturn(self::STUB_REPORT_ONLY); + + $this->assertInstanceOf(ModeConfigured::class, $this->model->getConfigured()); + } + + /** + * Data Provider with appropriate areas. + * + * @return array + */ + public function dataProviderGetConfiguredWithCorrectArea(): array + { + return [ + [ + 'area' => Area::AREA_ADMINHTML, + 'pathReportOnly' => 'csp/mode/admin/report_only', + 'pathReportUri' => 'csp/mode/admin/report_uri' + ], + [ + 'area' => Area::AREA_FRONTEND, + 'pathReportOnly' => 'csp/mode/storefront/report_only', + 'pathReportUri' => 'csp/mode/storefront/report_uri' + ] + ]; + } + + /** + * Test case with an inappropriate Area code. + */ + public function testGetConfiguredWithWrongArea() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode') + ->willReturn(self::STUB_AREA_CODE_OTHER); + + $this->configMock->expects($this->never())->method('isSetFlag'); + $this->configMock->expects($this->never())->method('getValue'); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('CSP can only be configured for storefront or admin area'); + + $this->model->getConfigured(); + } +} 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..48d6d6d9b4592 --- /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 MockObject|Render $renderObserver */ + $renderObserver = $objectManagerHelper->getObject( + Render::class, + ['cspRenderer' => $cspRendererMock] + ); + $renderObserver->execute($eventObserverMock); + } +} From 128535fb38ddeba06738333940583a11721640d7 Mon Sep 17 00:00:00 2001 From: Nikita Sarychev <sarron80@yandex.ru> Date: Fri, 7 Feb 2020 20:10:02 +0300 Subject: [PATCH 540/666] add preferences to di --- app/code/Magento/Catalog/etc/di.xml | 1 + 1 file changed, 1 insertion(+) 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> From 0aef9add469dda3a0102b886b008757469bb8f26 Mon Sep 17 00:00:00 2001 From: konarshankar07 <konar.shankar2013@gmail.com> Date: Sat, 8 Feb 2020 01:16:03 +0530 Subject: [PATCH 541/666] feedback changes --- .../Ui/base/js/grid/data-storage.test.js | 178 ++---------------- 1 file changed, 17 insertions(+), 161 deletions(-) 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 ade7d09797139..33c2e97e0b85f 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 @@ -31,20 +31,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('initConfig')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.initConfig; - - expect(type).toEqual('function'); - }); - - it('Check returned value if method called without arguments', function () { - expect(model.initConfig()).toBeDefined(); - }); - it('Check returned value type if method called without arguments', function () { var type = typeof model.initConfig(); @@ -70,20 +56,6 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getByIds')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getByIds).toEqual('function'); - }); - - it('Check returned value if method called with argument', function () { - var ids = [1,2,3]; - - expect(model.getByIds(ids)).toBeDefined(); - }); - it('check returned type if method called with argument', function () { var ids = [1,2,3], type = typeof model.getByIds(ids); @@ -98,7 +70,13 @@ define([ }); it('Return array if "getByIds" has been called', function () { - var ids = [1]; + var ids = [1], + expectedValue = [ + { + id_field_name: 'entity_id', + entity_id: '1' + } + ]; model = new DataStorage({ dataScope: 'magento', @@ -110,7 +88,7 @@ define([ } }); - expect(typeof model.getByIds(ids)).toEqual('object'); + expect(model.getByIds(ids)).toEqual(expectedValue); }); }); @@ -121,25 +99,15 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getIds')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getIds).toEqual('function'); - }); - - it('check returned value if method called with argument', function () { - var ids = [1,2,3]; - - expect(model.getIds(ids)).toBeDefined(); - }); - - it('check returned type if method called with argument', function () { - var ids = [1,2,3], - type = typeof model.getIds(ids); - - expect(type).toEqual('object'); + it('check array of entity_id will return', function () { + var ids = [ + { + id_field_name: 'entity_id', + entity_id: '1' + } + ], + expectedValue = ['1']; + expect(model.getIds(ids)).toEqual(expectedValue); }); }); @@ -150,28 +118,6 @@ define([ dataScope: 'magento' }); - it('check for defined', function () { - expect(model.hasOwnProperty('getData')).toBeDefined(); - }); - - it('check method type', function () { - expect(typeof model.getData).toEqual('function'); - }); - - it('check returned value if method called with argument', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; - - expect(model.getData(params)).toBeDefined(); - }); - it('check returned type if method called with argument', function () { var params = { namespace: 'magento', @@ -332,16 +278,6 @@ define([ } }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('updateData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.updateData; - - expect(type).toEqual('function'); - }); - it('Check updateData has been called', function () { var data = [{ id_field_name: 'entity_id', @@ -357,16 +293,6 @@ define([ dataScope: 'magento' }); - it('Check for defined', function () { - expect(model.hasOwnProperty('requestData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.requestData; - - expect(type).toEqual('function'); - }); - it('Check Ajax request', function () { var params = { namespace: 'magento', @@ -401,16 +327,6 @@ define([ dataScope: 'magento' }); - it('Check for defined', function () { - expect(model.hasOwnProperty('getRequest')).toBeDefined(); - }); - - it('Check method', function () { - var type = typeof model.getRequest; - - expect(type).toEqual('function'); - }); - it('check "getRequest" has been executed', function () { var params = { namespace: 'magento', @@ -434,16 +350,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('getRequestData')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.getRequestData; - - expect(type).toEqual('function'); - }); - it('check "getRequestData" has been executed', function () { var request = { ids: [1,2,3] @@ -495,16 +401,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('cacheRequest')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.cacheRequest; - - expect(type).toEqual('function'); - }); - it('check "model._requests"', function () { var params = { namespace: 'magento', @@ -559,16 +455,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('clearRequests')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.clearRequests; - - expect(type).toEqual('function'); - }); - it('check "clearRequests" will empty _requests array', function () { var params = { namespace: 'magento', @@ -600,16 +486,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('removeRequest')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.removeRequest; - - expect(type).toEqual('function'); - }); - it('check "removeRequest" is defined', function () { var params = { namespace: 'magento', @@ -634,16 +510,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('wasRequested')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.wasRequested; - - expect(type).toEqual('function'); - }); - it('Return false if getRequest method returns false', function () { var params = { namespace: 'magento', @@ -664,16 +530,6 @@ define([ dataScope: 'magento' }); - it('Check for defined ', function () { - expect(model.hasOwnProperty('onRequestComplete')).toBeDefined(); - }); - - it('Check method type', function () { - var type = typeof model.onRequestComplete; - - expect(type).toEqual('function'); - }); - it('Check "updateData" method has been called', function () { var data = { items: [{ From d50683de23f628ac7c12b071a57476b96ccbe108 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Sat, 8 Feb 2020 02:26:33 +0530 Subject: [PATCH 542/666] [Analytics] Code refactor & covered unit test --- .../Analytics/ReportXml/QueryFactory.php | 67 +++-- .../Test/Unit/ReportXml/QueryFactoryTest.php | 248 ++++++++++-------- 2 files changed, 189 insertions(+), 126 deletions(-) diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index 5da7adf794215..3869691c5ad58 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -8,6 +8,9 @@ use Magento\Analytics\ReportXml\DB\SelectBuilderFactory; use Magento\Framework\App\CacheInterface; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\DB\Select; /** * Creates Query object according to configuration @@ -45,15 +48,21 @@ class QueryFactory */ private $selectHydrator; + /** + * @var Json|null + */ + private $jsonSerializer; + /** * QueryFactory constructor. * - * @param CacheInterface $queryCache - * @param SelectHydrator $selectHydrator + * @param CacheInterface $queryCache + * @param SelectHydrator $selectHydrator * @param ObjectManagerInterface $objectManager - * @param SelectBuilderFactory $selectBuilderFactory - * @param Config $config - * @param array $assemblers + * @param SelectBuilderFactory $selectBuilderFactory + * @param Config $config + * @param array $assemblers + * @param Json|null $jsonSerializer */ public function __construct( CacheInterface $queryCache, @@ -61,7 +70,8 @@ public function __construct( ObjectManagerInterface $objectManager, SelectBuilderFactory $selectBuilderFactory, Config $config, - array $assemblers + array $assemblers, + Json $jsonSerializer = null ) { $this->config = $config; $this->selectBuilderFactory = $selectBuilderFactory; @@ -69,12 +79,13 @@ public function __construct( $this->queryCache = $queryCache; $this->objectManager = $objectManager; $this->selectHydrator = $selectHydrator; + $this->jsonSerializer = $jsonSerializer ?: ObjectManager::getInstance()->get(Json::class); } /** * Returns query connection name according to configuration * - * @param string $queryConfig + * @param string $queryConfig * @return string */ private function getQueryConnectionName($queryConfig) @@ -89,7 +100,7 @@ private function getQueryConnectionName($queryConfig) /** * Create query according to configuration settings * - * @param string $queryName + * @param string $queryName * @return Query */ private function constructQuery($queryName) @@ -101,12 +112,29 @@ private function constructQuery($queryName) $selectBuilder = $assembler->assemble($selectBuilder, $queryConfig); } $select = $selectBuilder->create(); + return $this->createQueryObject( + $select, + $selectBuilder->getConnectionName(), + $queryConfig + ); + } + + /** + * Create query class using objectmanger + * + * @param Select $select + * @param string $connection + * @param array $queryConfig + * @return Query + */ + private function createQueryObject($select, $connection, $queryConfig) + { return $this->objectManager->create( Query::class, [ 'select' => $select, 'selectHydrator' => $this->selectHydrator, - 'connectionName' => $selectBuilder->getConnectionName(), + 'connectionName' => $connection, 'config' => $queryConfig ] ); @@ -115,26 +143,25 @@ private function constructQuery($queryName) /** * Creates query by name * - * @param string $queryName + * @param string $queryName * @return Query */ 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; } } diff --git a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php index 9a3805a50f167..7ea5a61082485 100644 --- a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php +++ b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php @@ -3,161 +3,207 @@ * 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. */ -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 ] ); } /** + * Get Query Data Mock + * + * @return array + */ + private function getQueryDataMock(): array + { + return [ + 'connectionName' => self::STUB_CONNECTION, + 'config' => [ + 'name' => self::STUB_QUERY_NAME, + 'connection' => self::STUB_CONNECTION + ], + 'select_parts' => [] + ]; + } + + /** + * ObjectManager Mock with Query class + * + * @param array $queryDataMock * @return void */ - public function testCreateCached() + private function createQueryObjectMock($queryDataMock): void { - $queryName = 'test_query'; + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with( + Query::class, + [ + 'select' => $this->selectMock, + 'selectHydrator' => $this->selectHydratorMock, + 'connectionName' => $queryDataMock['connectionName'], + 'config' => $queryDataMock['config'] + ] + ) + ->willReturn($this->queryMock); + } + + /** + * Test create() if query cached + * + * @return void + */ + public function testCreateIfQueryCached(): void + { + $queryName = self::STUB_QUERY_NAME; + $queryDataMock = $this->getQueryDataMock(); $this->queryCacheMock->expects($this->any()) ->method('load') ->with($queryName) - ->willReturn('{"connectionName":"sales","config":{},"select_parts":{}}'); + ->willReturn(json_encode($queryDataMock)); + + $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 +215,19 @@ public function testCreateCached() } /** + * Test create() if query not cached + * * @return void */ - public function testCreateNotCached() + public function testCreateIfQueryNotCached(): void { - $queryName = 'test_query'; + $queryName = self::STUB_QUERY_NAME; + $queryDataMock = $this->getQueryDataMock(); + $queryConfigMock = $queryDataMock['config']; - $queryConfigMock = [ - 'name' => 'test_query', - 'connection' => 'sales' - ]; - - $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,22 +257,15 @@ public function testCreateNotCached() ->with($selectBuilderMock, $queryConfigMock) ->willReturn($selectBuilderMock); - $this->objectManagerMock->expects($this->once()) - ->method('create') - ->with( - \Magento\Analytics\ReportXml\Query::class, - [ - 'select' => $this->selectMock, - 'selectHydrator' => $this->selectHydratorMock, - 'connectionName' => $queryConfigMock['connection'], - 'config' => $queryConfigMock - ] - ) + $this->createQueryObjectMock($queryDataMock); + + $this->jsonSerializerMock->expects($this->once()) + ->method('serialize') ->willReturn($this->queryMock); $this->queryCacheMock->expects($this->once()) ->method('save') - ->with(json_encode($this->queryMock), $queryName); + ->with($this->queryMock, $queryName); $this->assertEquals( $this->queryMock, From f9697f509ae09f5c9e0f0d7b1a2de7ed9a53fc16 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Sat, 8 Feb 2020 03:02:17 +0530 Subject: [PATCH 543/666] Critical scope css fixed --- app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index a3f054d7c8dc7..f0c343c366abc 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 ); From 53c1e404a04e051880b97de2d719654ac4d6a1de Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Sat, 8 Feb 2020 03:29:27 +0530 Subject: [PATCH 544/666] Fixed static test --- app/code/Magento/Analytics/ReportXml/QueryFactory.php | 1 + .../Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index 3869691c5ad58..2293a242c453a 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -14,6 +14,7 @@ /** * Creates Query object according to configuration + * * Factory for @see \Magento\Analytics\ReportXml\Query */ class QueryFactory diff --git a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php index 7ea5a61082485..1a11b293400db 100644 --- a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php +++ b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php @@ -25,6 +25,8 @@ /** * A unit test for testing of the query factory. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class QueryFactoryTest extends TestCase { From 3e0ffb71b3dbb57dcda10ceac73abd87e5834555 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sat, 8 Feb 2020 11:42:25 +0530 Subject: [PATCH 545/666] No marginal space validation added --- .../Cms/view/adminhtml/ui_component/cms_block_listing.xml | 1 + 1 file changed, 1 insertion(+) 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> From e0015b4a7efbaba8b370b30ecc9e70357801183b Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sat, 8 Feb 2020 12:02:27 +0530 Subject: [PATCH 546/666] Covered validation with MFTF test --- .../AdminFillCmsBlockFormActionGroup.xml | 25 ++++++++++++++++ .../Mftf/Test/AdminCreateCmsBlockTest.xml | 30 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml 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/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index ef4a7575c35d3..a2dafc5e3537d 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -49,4 +49,34 @@ <see userInput="You saved the block." stepKey="seeSavedBlockMsgOnGrid"/> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> + <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"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + </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> From aafce6541753a29f55ff87929acc0b3698ec0cf4 Mon Sep 17 00:00:00 2001 From: Pratik Mehta <pratik@seepossible.com> Date: Sat, 8 Feb 2020 13:15:26 +0530 Subject: [PATCH 547/666] Translation values add in translation file. --- app/code/Magento/Backend/i18n/en_US.csv | 2 ++ 1 file changed, 2 insertions(+) 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]" From 7d695bdc60658bbaec89050f0bf77da7cced81e4 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sat, 8 Feb 2020 16:40:14 +0530 Subject: [PATCH 548/666] Removed unnecessary function argument --- app/code/Magento/Sales/Model/Order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 89564f97ccf16..aee8432fb0925 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(); } /** From 180f896005c4b8d4077760d441d930bbe41fde3b Mon Sep 17 00:00:00 2001 From: Grayson <grayson@astralwebinc.com> Date: Sat, 8 Feb 2020 22:38:01 +0800 Subject: [PATCH 549/666] fix the isset code style --- app/code/Magento/Bundle/Helper/Data.php | 2 +- .../Edit/Tab/Price/Group/AbstractGroup.php | 2 +- .../Model/Product/Attribute/Source/Status.php | 2 +- .../Model/Product/Gallery/EntryResolver.php | 4 ++-- .../Catalog/Model/Product/Visibility.php | 2 +- .../ProductLink/Converter/ConverterPool.php | 4 +--- .../Catalog/Model/ProductLink/Link.php | 2 +- .../Block/Checkout/AttributeMerger.php | 7 +++--- .../Config/Structure/AbstractElement.php | 6 ++--- .../Model/Config/Structure/Element/Field.php | 8 +++---- .../Config/Structure/Element/Section.php | 2 +- .../Customer/Ui/Component/ColumnFactory.php | 4 +--- .../Customer/Ui/Component/FilterFactory.php | 2 +- .../Component/Listing/AttributeRepository.php | 4 ++-- .../Listing/Column/ValidationRules.php | 4 +--- .../Customer/Ui/Component/Listing/Columns.php | 2 +- app/code/Magento/Deploy/Model/Mode.php | 2 +- app/code/Magento/Deploy/Package/Package.php | 4 ++-- .../Magento/Deploy/Package/PackagePool.php | 4 ++-- .../Deploy/Service/DeployStaticContent.php | 2 +- app/code/Magento/Deploy/Source/SourcePool.php | 2 +- app/code/Magento/Dhl/Model/Carrier.php | 4 ++-- .../Dhl/Test/Unit/Model/CarrierTest.php | 2 +- .../CollectionProcessor/FilterProcessor.php | 2 +- app/code/Magento/Eav/Model/Config.php | 6 ++--- .../Attribute/Source/AbstractSource.php | 2 +- .../Entity/Setup/PropertyMapperAbstract.php | 2 +- app/code/Magento/Eav/Model/Entity/Type.php | 8 +++---- .../Eav/Model/TypeLocator/SimpleType.php | 3 +-- app/code/Magento/Eav/Setup/EavSetup.php | 4 ++-- .../ImportExport/Model/Export/Config.php | 2 +- .../Gateway/Data/Order/AddressAdapter.php | 4 ++-- .../Gateway/Data/Quote/AddressAdapter.php | 4 ++-- app/code/Magento/Payment/Model/Info.php | 2 +- app/code/Magento/Paypal/Model/AbstractIpn.php | 2 +- app/code/Magento/Paypal/Model/Config.php | 2 +- app/code/Magento/Paypal/Model/Info.php | 22 +++++-------------- .../Paypal/Model/Payflow/AvsEmsCodeMapper.php | 2 +- .../Paypal/Model/Payflow/CvvEmsCodeMapper.php | 2 +- app/code/Magento/Paypal/Model/Payflowpro.php | 2 +- .../Store/Model/Config/Processor/Fallback.php | 2 +- .../Store/Test/Unit/Model/InformationTest.php | 2 +- .../Theme/Model/Theme/ThemePackageInfo.php | 5 ++--- .../Ui/Component/AbstractComponent.php | 2 +- .../Ui/Config/Reader/Definition/Data.php | 2 +- .../Ui/DataProvider/AbstractDataProvider.php | 10 ++++----- app/code/Magento/Ui/Model/Manager.php | 5 ++--- app/code/Magento/Ups/Model/Carrier.php | 2 +- .../Ups/Test/Unit/Model/CarrierTest.php | 2 +- app/code/Magento/User/Block/Role/Tab/Edit.php | 2 +- .../Usps/Test/Unit/Model/CarrierTest.php | 2 +- 51 files changed, 81 insertions(+), 103 deletions(-) diff --git a/app/code/Magento/Bundle/Helper/Data.php b/app/code/Magento/Bundle/Helper/Data.php index dbd4a6a039c27..3997cac4e0c8d 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/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/Model/Product/Attribute/Source/Status.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php index 24abb8471d477..92d3c9513ba40 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php @@ -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/Gallery/EntryResolver.php b/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php index 36eb71abe2a5d..c706673ed222e 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php @@ -27,7 +27,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 +49,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/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/ProductLink/Converter/ConverterPool.php b/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php index f58d1d6b69be8..e90dc3c6b04b4 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php @@ -34,8 +34,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..ad779eb0723b1 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Link.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Link.php @@ -30,7 +30,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; } /** diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 5dedf2c7e7eba..6e0bfe42547fd 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -197,7 +197,7 @@ protected function getFieldConfig( ? $additionalConfig['sortOrder'] : $attributeConfig['sortOrder'], 'validation' => $this->mergeConfigurationNode('validation', $additionalConfig, $attributeConfig), - 'options' => $this->getFieldOptions($attributeCode, $attributeConfig), + 'options' => $this->getFieldOptions($attributeConfig), 'filterBy' => isset($additionalConfig['filterBy']) ? $additionalConfig['filterBy'] : null, 'customEntry' => isset($additionalConfig['customEntry']) ? $additionalConfig['customEntry'] : null, 'visible' => isset($additionalConfig['visible']) ? $additionalConfig['visible'] : true, @@ -381,14 +381,13 @@ protected function getCustomer(): ?CustomerInterface /** * Retrieve field options from attribute configuration * - * @param string $attributeCode * @param array $attributeConfig * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - protected function getFieldOptions($attributeCode, array $attributeConfig) + protected function getFieldOptions(array $attributeConfig) { - return isset($attributeConfig['options']) ? $attributeConfig['options'] : []; + return $attributeConfig['options'] ?? []; } /** 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..e73bac986ad23 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Element/Section.php +++ b/app/code/Magento/Config/Model/Config/Structure/Element/Section.php @@ -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/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..d931a6770012b 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -156,10 +156,10 @@ protected function getOptionArray(array $options) * Return customer group's metadata by given group code * * @param string $code - * @return [] + * @return string 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..c18e538f9365f 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -200,6 +200,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/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 423f3072c4620..e1a6697b79036 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..17f5ca2425a89 100644 --- a/app/code/Magento/Deploy/Package/PackagePool.php +++ b/app/code/Magento/Deploy/Package/PackagePool.php @@ -66,7 +66,7 @@ public function __construct( public function getPackage($path) { $this->collect(); - return isset($this->packages[$path]) ? $this->packages[$path] : null; + return $this->packages[$path] ?? null; } /** @@ -322,7 +322,7 @@ private function isIncluded($entity, array $includedEntities, array $excludedEnt */ private function getOption($name, $options) { - return isset($options[$name]) ? $options[$name] : null; + return $options[$name] ?? null; } /** diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index b6333d6fec71e..69d20676b3f0b 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/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php b/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php index c24f87d36d64b..1625048ac92b8 100644 --- a/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php +++ b/app/code/Magento/Eav/Model/Api/SearchCriteria/CollectionProcessor/FilterProcessor.php @@ -113,6 +113,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..98af6e9f9c280 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,7 +239,7 @@ protected function _load($id) */ private function loadAttributes($entityTypeCode) { - return isset($this->attributes[$entityTypeCode]) ? $this->attributes[$entityTypeCode] : []; + return $this->attributes[$entityTypeCode] ?? []; } /** @@ -290,7 +290,7 @@ 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; } /** 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/Setup/PropertyMapperAbstract.php b/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php index 87ff3a9d22bfd..a3b234181707c 100644 --- a/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php +++ b/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php @@ -22,6 +22,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..81ceb26419633 100644 --- a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php +++ b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php @@ -59,8 +59,7 @@ 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; } /** diff --git a/app/code/Magento/Eav/Setup/EavSetup.php b/app/code/Magento/Eav/Setup/EavSetup.php index d440a84fc8e65..9e2eda92d66ce 100644 --- a/app/code/Magento/Eav/Setup/EavSetup.php +++ b/app/code/Magento/Eav/Setup/EavSetup.php @@ -797,7 +797,7 @@ private 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; } /** @@ -1102,7 +1102,7 @@ public function getAttribute($entityTypeId, $id, $field = null) $row = $setupCache->get($mainTable, $entityTypeId, $id); if ($field !== null) { - return isset($row[$field]) ? $row[$field] : false; + return $row[$field] ?? false; } return $row; diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php index 9e7cd6a29dc9a..991bdb0984d36 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config.php +++ b/app/code/Magento/ImportExport/Model/Export/Config.php @@ -48,7 +48,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/Payment/Gateway/Data/Order/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php index f4b05df2e8a20..9c0c2ea2afeae 100644 --- a/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php +++ b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php @@ -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..a68dc1194c9f9 100644 --- a/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php +++ b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php @@ -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/Paypal/Model/AbstractIpn.php b/app/code/Magento/Paypal/Model/AbstractIpn.php index 14d8163fd3bb3..ec7e42a0f24b1 100644 --- a/app/code/Magento/Paypal/Model/AbstractIpn.php +++ b/app/code/Magento/Paypal/Model/AbstractIpn.php @@ -68,7 +68,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; } /** diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index e197218752bf5..0cca6f219977e 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']; } /** diff --git a/app/code/Magento/Paypal/Model/Info.php b/app/code/Magento/Paypal/Model/Info.php index bb2e9366e588f..9e9423d7ac61e 100644 --- a/app/code/Magento/Paypal/Model/Info.php +++ b/app/code/Magento/Paypal/Model/Info.php @@ -518,9 +518,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.'); } /** @@ -542,7 +540,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 +609,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] ?? ''; } /** @@ -705,9 +701,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 +731,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 +748,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..5c310816a975f 100644 --- a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php +++ b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php @@ -64,6 +64,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..856040a378a5a 100644 --- a/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php +++ b/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php @@ -58,6 +58,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/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 2ba72c4b26bd7..7557b6fc9474f 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -980,6 +980,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/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/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/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/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index 772bdceeb4957..ba1abc62f522a 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -178,7 +178,7 @@ public function addComponent($name, UiComponentInterface $component) */ public function getComponent($name) { - return isset($this->components[$name]) ? $this->components[$name] : null; + return $this->components[$name] ?? null; } /** diff --git a/app/code/Magento/Ui/Config/Reader/Definition/Data.php b/app/code/Magento/Ui/Config/Reader/Definition/Data.php index 62bb07a6486f5..32dd5a52edd91 100644 --- a/app/code/Magento/Ui/Config/Reader/Definition/Data.php +++ b/app/code/Magento/Ui/Config/Reader/Definition/Data.php @@ -123,7 +123,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..c403aedbd2638 100644 --- a/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php +++ b/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php @@ -127,7 +127,7 @@ public function getMeta() */ public function getFieldSetMetaInfo($fieldSetName) { - return isset($this->meta[$fieldSetName]) ? $this->meta[$fieldSetName] : []; + return $this->meta[$fieldSetName] ?? []; } /** @@ -136,7 +136,7 @@ public function getFieldSetMetaInfo($fieldSetName) */ public function getFieldsMetaInfo($fieldSetName) { - return isset($this->meta[$fieldSetName]['children']) ? $this->meta[$fieldSetName]['children'] : []; + return $this->meta[$fieldSetName]['children'] ?? []; } /** @@ -146,9 +146,7 @@ public function getFieldsMetaInfo($fieldSetName) */ public function getFieldMetaInfo($fieldSetName, $fieldName) { - return isset($this->meta[$fieldSetName]['children'][$fieldName]) - ? $this->meta[$fieldSetName]['children'][$fieldName] - : []; + return $this->meta[$fieldSetName]['children'][$fieldName] ?? []; } /** @@ -270,7 +268,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/Manager.php b/app/code/Magento/Ui/Model/Manager.php index e3c56418c8425..64ae7271fed8b 100644 --- a/app/code/Magento/Ui/Model/Manager.php +++ b/app/code/Magento/Ui/Model/Manager.php @@ -386,8 +386,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/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/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/User/Block/Role/Tab/Edit.php b/app/code/Magento/User/Block/Role/Tab/Edit.php index 5fe6a1b2a2e88..f2663e29705d4 100644 --- a/app/code/Magento/User/Block/Role/Tab/Edit.php +++ b/app/code/Magento/User/Block/Role/Tab/Edit.php @@ -222,6 +222,6 @@ function ($node) { } ); $configResource = reset($configResource); - return isset($configResource['children']) ? $configResource['children'] : []; + return $configResource['children'] ?? []; } } 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; } /** From 353beeeea769ff96e780979d53a8489ea4099b4e Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 9 Feb 2020 00:04:47 +0530 Subject: [PATCH 550/666] Test is moved to seperate file --- .../Mftf/Test/AdminCreateCmsBlockTest.xml | 30 -------------- ...minCreateCmsBlockWithMarginalSpaceTest.xml | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index d357eaf50d29e..6867560551915 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -42,34 +42,4 @@ <actionGroup ref="SaveAndCloseCMSBlockWithSplitButtonActionGroup" stepKey="saveAndCloseAction" /> <seeElement selector="div[data-role='grid-wrapper']" stepKey="seeGridPage" /> </test> - <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"/> - </annotations> - <before> - <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> - </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/AdminCreateCmsBlockWithMarginalSpaceTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml new file mode 100644 index 0000000000000..0399d0eb3ab28 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml @@ -0,0 +1,41 @@ +<?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"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + </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> From e500c3d89a52edf69df1753db1524a0dd560ce16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Wed, 15 Jan 2020 12:19:14 +0100 Subject: [PATCH 551/666] Move additional dependencies from private getters to constructor - Magento_Captcha --- .../Observer/CheckContactUsFormObserver.php | 65 ++++---- .../CheckContactUsFormObserverTest.php | 148 ++++++++++-------- 2 files changed, 110 insertions(+), 103 deletions(-) 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/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()); } } From dd9c0d1bf25c07aaef3fddefd51454ba209b3fcc Mon Sep 17 00:00:00 2001 From: Grayson <grayson@astralwebinc.com> Date: Sun, 9 Feb 2020 11:07:13 +0800 Subject: [PATCH 552/666] fix review unnesseay change files --- app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php | 4 ++-- app/code/Magento/Deploy/Service/DeployStaticContent.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 6e0bfe42547fd..4543f1af61dc1 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -197,7 +197,7 @@ protected function getFieldConfig( ? $additionalConfig['sortOrder'] : $attributeConfig['sortOrder'], 'validation' => $this->mergeConfigurationNode('validation', $additionalConfig, $attributeConfig), - 'options' => $this->getFieldOptions($attributeConfig), + 'options' => $this->getFieldOptions($attributeCode, $attributeConfig), 'filterBy' => isset($additionalConfig['filterBy']) ? $additionalConfig['filterBy'] : null, 'customEntry' => isset($additionalConfig['customEntry']) ? $additionalConfig['customEntry'] : null, 'visible' => isset($additionalConfig['visible']) ? $additionalConfig['visible'] : true, @@ -385,7 +385,7 @@ protected function getCustomer(): ?CustomerInterface * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - protected function getFieldOptions(array $attributeConfig) + protected function getFieldOptions($attributeCode, array $attributeConfig) { return $attributeConfig['options'] ?? []; } diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index 69d20676b3f0b..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 (int)$options[Options::JOBS_AMOUNT] ?? 0; + return (int)($options[Options::JOBS_AMOUNT] ?? 0); } /** From 5cba788f4bab739c51f47823b133e159e615b517 Mon Sep 17 00:00:00 2001 From: Grayson <grayson@astralwebinc.com> Date: Sun, 9 Feb 2020 11:13:42 +0800 Subject: [PATCH 553/666] revert retuen code --- .../Customer/Ui/Component/Listing/AttributeRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index d931a6770012b..d577883673dcd 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php @@ -156,7 +156,7 @@ protected function getOptionArray(array $options) * Return customer group's metadata by given group code * * @param string $code - * @return string null + * @return array | null */ public function getMetadataByCode($code) { From 9e789ca3328035ba494f6575362c29ea955e80a9 Mon Sep 17 00:00:00 2001 From: Matthew O'Loughlin <matthew.oloughlin@aligent.com.au> Date: Sun, 9 Feb 2020 18:03:07 +1030 Subject: [PATCH 554/666] Fix return type to match function spec (empty array instead of null) --- .../Magento/BundleGraphQl/Model/Resolver/Options/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php index 7608d6e9e4d97..23bfbb5fc4e22 100644 --- a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php +++ b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php @@ -115,7 +115,7 @@ private function fetch() : array $this->extensionAttributesJoinProcessor->process($optionsCollection); if (empty($optionsCollection->getData())) { - return null; + return []; } /** @var \Magento\Bundle\Model\Option $option */ From 4238f7bf202e763186c2a78386ca98fdaf682de9 Mon Sep 17 00:00:00 2001 From: Matthew O'Loughlin <matthew.oloughlin@aligent.com.au> Date: Sun, 9 Feb 2020 18:09:00 +1030 Subject: [PATCH 555/666] Also switch to null-coalescing for cleanliness --- .../BundleGraphQl/Model/Resolver/Options/Collection.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php b/app/code/Magento/BundleGraphQl/Model/Resolver/Options/Collection.php index 23bfbb5fc4e22..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] ?? []; } /** From 9c75294d25182a1ada90ad66c621dcf9b39941fa Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Sun, 9 Feb 2020 10:14:46 +0200 Subject: [PATCH 556/666] Fix docblock for the variable --- app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php index 48d6d6d9b4592..8c42a4d051bde 100644 --- a/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php +++ b/app/code/Magento/Csp/Test/Unit/Observer/RenderTest.php @@ -42,7 +42,7 @@ public function testExecuteExpectsRenderCalled() $cspRendererMock->expects($this->once())->method('render'); $objectManagerHelper = new ObjectManager($this); - /** @var MockObject|Render $renderObserver */ + /** @var Render $renderObserver */ $renderObserver = $objectManagerHelper->getObject( Render::class, ['cspRenderer' => $cspRendererMock] From dccf5ef6b40f50c33baadcc323f52686df134753 Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 9 Feb 2020 14:45:04 +0530 Subject: [PATCH 557/666] Delete action added for CMS page creation MTFT test --- app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index e6fcbab4de644..838ed025e98b6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -29,6 +29,9 @@ <actionGroup ref="CreateNewPageWithBasicValues" stepKey="createNewPageWithBasicValues" /> <actionGroup ref="SaveCmsPageActionGroup" stepKey="clickSaveCmsPageButton" /> <actionGroup ref="VerifyCreatedCmsPage" stepKey="verifyCmsPage" /> + <actionGroup ref="DeletePageByUrlKeyActionGroup" stepKey="deletePage"> + <argument name="UrlKey" value="{{_defaultCmsPage.identifier}}"/> + </actionGroup> </test> <test name="AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest"> <annotations> From eff07be5df168b7e90bcedaf20698a9af0d7b78d Mon Sep 17 00:00:00 2001 From: Ajith <ajithkumar.maragathavel@ziffity.com> Date: Sun, 9 Feb 2020 15:39:39 +0530 Subject: [PATCH 558/666] Moved tests to seperate file --- ...PageLayoutFromConfigurationSettingTest.xml | 44 ++++++++++++ .../Test/Mftf/Test/AdminCreateCmsPageTest.xml | 71 ------------------- .../Test/AdminCreateDuplicatedCmsPageTest.xml | 49 +++++++++++++ 3 files changed, 93 insertions(+), 71 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminConfigDefaultCMSPageLayoutFromConfigurationSettingTest.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml 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..ee06b4ce86656 --- /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="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> +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index 838ed025e98b6..7fd39ab5bb1d6 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -33,75 +33,4 @@ <argument name="UrlKey" value="{{_defaultCmsPage.identifier}}"/> </actionGroup> </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" /> - </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..cf333f8b559d0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml @@ -0,0 +1,49 @@ +<?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"/> + </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" /> + </test> +</tests> From 7ef0c88e9c0b452a5e43ad0189a052a4dab500a8 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Sun, 9 Feb 2020 23:31:38 +0000 Subject: [PATCH 559/666] magento/magento2#26502: Code review changes --- .../Ui/base/js/grid/data-storage.test.js | 657 ++++++++---------- 1 file changed, 287 insertions(+), 370 deletions(-) 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 33c2e97e0b85f..da2e4ace72f7c 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 @@ -7,257 +7,186 @@ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ define([ 'jquery', - 'mageUtils', - 'underscore', 'Magento_Ui/js/grid/data-storage' -], function ($, utils, _, DataStorage) { +], function ($, DataStorage) { 'use strict'; describe('Magento_Ui/js/grid/data-storage', function () { - describe('constructor', 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('"initConfig" method', function () { + it('changes string dataScope property to an array', function () { + var model = new DataStorage({ + dataScope: 'magento' + }); - var model = new DataStorage({ - dataScope: 'magento' + expect(model.dataScope).toEqual(['magento']); }); - it('Check returned value type if method called without arguments', function () { - var type = typeof model.initConfig(); + it('changes empty string dataScope property to an empty array', function () { + var model = new DataStorage({ + dataScope: '' + }); - expect(type).toEqual('object'); + expect(model.dataScope).toEqual([]); }); - it('Check this.dataScope property (is modify in initConfig method)', function () { - model.dataScope = null; - model.initConfig(); - expect(typeof model.dataScope).toEqual('object'); + it('doesn\'t change non-string dataScope property', function () { + var testScope = { + testKey: 'test value' + }, + model = new DataStorage({ + dataScope: testScope + }); + + expect(model.dataScope).toEqual(testScope); }); - it('Check this._requests property (is modify in initConfig method)', function () { + it('initializes _requests property as an empty array', function () { + var model = new DataStorage(); model._requests = null; model.initConfig(); - expect(typeof model._requests).toEqual('object'); + expect(model._requests).toEqual([]); }); }); describe('"getByIds" method', function () { - var model = new DataStorage({ - dataScope: 'magento' + it('returns false if data for ids is missing', function () { + var model = new DataStorage(); + + expect(model.getByIds([1,2,3])).toEqual(false); }); - it('check returned type if method called with argument', function () { - var ids = [1,2,3], - type = typeof model.getByIds(ids); + it('returns array of items', function () { + var item = { + id_field_name: 'entity_id', + entity_id: '1' + }, + model = new DataStorage({ + data: { + 1: item + } + }); - expect(type).toEqual('boolean'); + expect(model.getByIds([1])).toEqual([item]); }); - it('Return false if "getByIds" has been called', function () { - var ids = [1,2,3]; + }); - expect(model.getByIds(ids)).toEqual(false); - }); + describe('"getIds" method', function () { - it('Return array if "getByIds" has been called', function () { - var ids = [1], - expectedValue = [ + 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' - } - ]; - - model = new DataStorage({ - dataScope: 'magento', - data: { - 1: { + }, + { id_field_name: 'entity_id', - entity_id: '1' + entity_id: '54' } - } - }); + ]; - expect(model.getByIds(ids)).toEqual(expectedValue); + expect(model.getIds(ids)).toEqual(['1', '54']); }); - }); - - describe('"getIds" method', function () { + 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' + }, + } + }); - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check array of entity_id will return', function () { - var ids = [ - { - id_field_name: 'entity_id', - entity_id: '1' - } - ], - expectedValue = ['1']; - expect(model.getIds(ids)).toEqual(expectedValue); + expect(model.getIds()).toEqual(['1', '42']); }); }); describe('"getData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check returned type if method called with argument', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - type = typeof model.getData(params); - - expect(type).toEqual('object'); - }); + var model = new DataStorage(); - it('check "clearRequests" has been called', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; + it('returns the result of requestData method if scope have been changed', function () { + var requestDataResult = 'requestDataResult'; spyOn(model, 'clearRequests'); - spyOn(model, 'hasScopeChanged').and.callFake(function () { - return true; - }); - model.getData(params); + spyOn(model, 'hasScopeChanged').and.returnValue(true); + spyOn(model, 'requestData').and.returnValue(requestDataResult); + expect(model.getData()).toEqual(requestDataResult); expect(model.clearRequests).toHaveBeenCalled(); }); - it('check "getRequest" has been called', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }; + it('returns the cached result if scope have not been changed', function () { + var cachedRequestDataResult = 'cachedRequestDataResult'; - spyOn(model, 'getRequest'); - spyOn(model, 'hasScopeChanged').and.callFake(function () { - return false; - }); - model.getData(params); - expect(model.getRequest).toHaveBeenCalled(); - }); - - it('it returns cached request data if a cached request exists and no refresh option is provided', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - options = { - refresh: false - }; + spyOn(model, 'clearRequests'); + spyOn(model, 'requestData'); + spyOn(model, 'hasScopeChanged').and.returnValue(false); + spyOn(model, 'getRequest').and.returnValue(true); + spyOn(model, 'getRequestData').and.returnValue(cachedRequestDataResult); - spyOn(model, 'getRequestData'); - spyOn(model, 'getRequest').and.callFake(function () { - return true; - }); - model.getData(params, options); - expect(model.getRequestData).toHaveBeenCalled(); + expect(model.getData()).toEqual(cachedRequestDataResult); + expect(model.clearRequests).not.toHaveBeenCalled(); + expect(model.requestData).not.toHaveBeenCalled(); }); - it('if refresh option is true so it will ignore cache and execute the requestData function', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, + it('returns the result of requestData method if refresh option is provided', function () { + var requestDataResult = 'requestDataResult', options = { refresh: true }; - spyOn(model, 'requestData'); - spyOn(model, 'getRequest').and.callFake(function () { - return false; - }); - model.getData(params, options); - expect(model.requestData).toHaveBeenCalled(); + 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('is function', function () { - var model = new DataStorage({ - dataScope: '' - }); - - expect(model.hasScopeChanged).toBeDefined(); - expect(typeof model.hasScopeChanged).toEqual('function'); - }); it('returns false if no requests have been made', function () { - var model = new DataStorage({ - dataScope: '' - }); + var model = new DataStorage(); expect(model.hasScopeChanged()).toBeFalsy(); }); - it('tells whether parameters defined in the dataScope property have changed', function () { - var params, newParams, model; - - params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 + it('returns true for not cached params', function () { + var params = { + search: '1', + filters: { + store_id: 0 + } }, - sorting: {}, - paging: {} - }; - - newParams = utils.extend({}, params, { - search: 'magento', - filters: { - store_id: 1 - } - }); - - model = new DataStorage({ - dataScope: 'filters.store_id' - }); + newParams = { + search: '2', + filters: { + store_id: 1 + } + }, + model = new DataStorage({ + dataScope: 'filters.store_id' + }); model.cacheRequest({ totalRecords: 0 @@ -275,50 +204,47 @@ define([ url: 'magento.com', method: 'GET', dataType: 'json' + }, + data: { + 1: { + id_field_name: 'entity_id', + entity_id: '1', + field: 'value' + }, } }); - it('Check updateData has been called', function () { + it('updates data items', function () { var data = [{ id_field_name: 'entity_id', - entity_id: '1' + entity_id: '1', + field: 'updatedValue' }]; - expect(model.updateData(data)).toBeTruthy(); + expect(model.updateData(data)).toEqual(model); + expect(model.getByIds([1])).toEqual(data); }); }); describe('"requestData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); + var model = new DataStorage(); it('Check Ajax request', function () { - var params = { - namespace: 'magento', - search: '', - filters: { - store_id: 0 - }, - sorting: {}, - paging: {} - }, - query = utils.copy(params); - - spyOn(model, 'onRequestComplete'); - spyOn($, 'ajax').and.callFake(function () { - return { - /** - * Success result for ajax request - */ - done: function () { - model.onRequestComplete(model, query); - } - }; + var result = 'result'; + + spyOn(model, 'onRequestComplete').and.returnValue(result); + spyOn($, 'ajax').and.returnValue({ + /** + * Success result for ajax request + * + * @param handler + * @returns {*} + */ + done: function (handler) { + return handler(); + } }); - model.requestData(params); - expect($.ajax).toHaveBeenCalled(); - expect(model.onRequestComplete).toHaveBeenCalled(); + expect(model.requestData({})).toEqual(result); }); }); @@ -327,72 +253,54 @@ define([ dataScope: 'magento' }); - it('check "getRequest" has been executed', function () { + it('returns cached request', function () { var params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }; + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1'], + params: params, + totalRecords: 1, + errorMessage: '' + }; - model._requests.push({ - ids: ['1'], - params: params, - totalRecords: 1, - errorMessage: '' - }); - expect(model.getRequest(params)).toBeTruthy(); + model._requests.push(request); + expect(model.getRequest(params)).toEqual(request); }); }); describe('"getRequestData" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check "getRequestData" has been executed', function () { - var request = { - ids: [1,2,3] - }; - - expect(model.getRequestData(request)).toBeTruthy(); - }); - - it('check "getByIds" has been executed', function () { - var request = { - ids: [1,2,3] - }; - - spyOn(model, 'getByIds'); - model.getRequestData(request); - expect(model.getByIds).toHaveBeenCalled(); - }); - - it('check "delay" function has been executed', function () { + it('returns request data', function () { var request = { - ids: [1,2,3], - totalRecords: 3, - errorMessage: '' - }; - - spyOn(_, 'delay'); - model.getRequestData(request); - expect(_.delay).toHaveBeenCalled(); - }); - - it('check "delay" function has not been executed', function () { - var request = { - ids: [1,2,3], - totalRecords: 3, + ids: [1,2], + totalRecords: 2, errorMessage: '' - }; - model = new DataStorage({ - dataScope: 'magento', - cachedRequestDelay: 0 - }); - spyOn(_, 'delay'); - model.getRequestData(request); - expect(_.delay).not.toHaveBeenCalled(); + }, + 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) + }) }); }); @@ -401,73 +309,83 @@ define([ dataScope: 'magento' }); - it('check "model._requests"', function () { + it('adds the request to the cache', function () { var params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }, - data = { - items: ['1','2','3'], - totalRecords: 3 - }; + 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.callFake(function () { - return ['1','2','3']; - }); + spyOn(model, 'getIds').and.returnValue(ids); model.cacheRequest(data, params); - expect(typeof model._requests).toEqual('object'); - expect(model.getIds).toHaveBeenCalled(); + expect(model.getRequest(params)).toEqual(request); expect(model.removeRequest).not.toHaveBeenCalled(); }); - it('check "removeRequest" is executed', function () { + it('overwrites the previously cached request for the same params', function () { var params = { namespace: 'magento', search: '', sorting: {}, paging: {} }, - data = { - items: ['1','2','3'], - totalRecords: 3 + 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, 'removeRequest'); - spyOn(model, 'getRequest').and.callFake(function () { - return true; - }); - spyOn(model, 'getIds').and.callFake(function () { - return ['1','2','3']; - }); - model.cacheRequest(data, params); - expect(typeof model._requests).toEqual('object'); - expect(model.getIds).toHaveBeenCalled(); - expect(model.removeRequest).toHaveBeenCalled(); + 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 () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('check "clearRequests" will empty _requests array', function () { - var params = { - namespace: 'magento', - search: 'magento', - filters: { - store_id: 1 - } - }; - - model = new DataStorage({ - dataScope: 'magento', - _requests: [] - }); + 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'], @@ -482,26 +400,26 @@ define([ describe('"removeRequest" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); + var model = new DataStorage(); - it('check "removeRequest" is defined', function () { + it('removes the request from the cache', function () { var params = { - namespace: 'magento', - search: 'magento', - filters: { - store_id: 1 - } - }, - request = [{ - ids: [1,2,3], - params: params, - totalRecords: 3, - errorMessage: 'errorMessage' - }]; + namespace: 'magento', + search: '', + sorting: {}, + paging: {} + }, + request = { + ids: ['1','2','3'], + params: params, + totalRecords: 3, + errorMessage: '' + }; - expect(model.removeRequest(request)).toBeDefined(); + model._requests = [request]; + expect(model.getRequest(params)).toEqual(request); + model.removeRequest(request); + expect(model.getRequest(params)).toBeFalsy(); }); }); @@ -510,7 +428,7 @@ define([ dataScope: 'magento' }); - it('Return false if getRequest method returns false', function () { + it('returns false if request is not present in cache', function () { var params = { namespace: 'magento', search: '', @@ -518,61 +436,60 @@ define([ paging: {} }; - spyOn(model, 'getRequest').and.callFake(function () { - return false; - }); expect(model.wasRequested(params)).toBeFalsy(); }); - }); - describe('"onRequestComplete" method', function () { - var model = new DataStorage({ - dataScope: 'magento' - }); - - it('Check "updateData" method has been called', function () { - var data = { - items: [{ - id_field_name: 'entity_id', - entity_id: '1' - }] - }, - params = { + 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: '' }; - spyOn(model, 'updateData').and.callFake(function () { - return data; - }); + 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('Check "cacheRequest" method has been called', function () { - var data = { - items: [{ - id_field_name: 'entity_id', - entity_id: '1' - }] - }, - params = { - namespace: 'magento', - search: '', - sorting: {}, - paging: {} - }; + it('updates data and adds the request to cache if caching is enabled', function () { + var model = new DataStorage({ + cacheRequests: true + }), + data = { + items: [] + }, + params = {}; - model = new DataStorage({ - dataScope: 'magento', - cacheRequests: true - }); - spyOn(model, 'cacheRequest').and.callFake(function () { - return data; - }); + spyOn(model, 'updateData'); + spyOn(model, 'cacheRequest'); model.onRequestComplete(params, data); + expect(model.updateData).toHaveBeenCalled(); expect(model.cacheRequest).toHaveBeenCalled(); }); }); From 6d0fa267f2950dc6243a312d7a48d4b967be770e Mon Sep 17 00:00:00 2001 From: Slava Mankivski <mankivsk@adobe.com> Date: Sun, 9 Feb 2020 22:34:05 -0600 Subject: [PATCH 560/666] Updated composer.lock --- composer.lock | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 5b94f60fa80a9..d5f3f4917af7c 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": "7b6381bcafc7f064e10ee71099b7d50b", "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" }, { From a1d2a846d5752eb3708155ecc9468835d82f4504 Mon Sep 17 00:00:00 2001 From: Shankar Konar <konar.shankar2013@gmail.com> Date: Mon, 10 Feb 2020 11:25:47 +0530 Subject: [PATCH 561/666] Fixed static tests --- .../Magento/Ui/base/js/grid/data-storage.test.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) 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 da2e4ace72f7c..4fe7aff69d0e2 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 @@ -5,6 +5,8 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ +/*eslint newline-after-var: ["error", "always"]*/ +/*eslint-env es6*/ define([ 'jquery', 'Magento_Ui/js/grid/data-storage' @@ -52,6 +54,7 @@ define([ it('initializes _requests property as an empty array', function () { var model = new DataStorage(); + model._requests = null; model.initConfig(); expect(model._requests).toEqual([]); @@ -110,7 +113,7 @@ define([ 2: { id_field_name: 'entity_id', entity_id: '42' - }, + } } }); @@ -129,8 +132,10 @@ define([ 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 () { @@ -210,7 +215,7 @@ define([ id_field_name: 'entity_id', entity_id: '1', field: 'value' - }, + } } }); @@ -237,7 +242,7 @@ define([ /** * Success result for ajax request * - * @param handler + * @param {Function} handler * @returns {*} */ done: function (handler) { @@ -297,10 +302,11 @@ define([ model = new DataStorage({ cachedRequestDelay: 0 }); + spyOn(model, 'getByIds').and.returnValue(items); model.getRequestData(request).then(function (promiseResult) { - expect(promiseResult).toEqual(result) - }) + expect(promiseResult).toEqual(result); + }); }); }); From 1f2ed9035507c8ebf46ddacd0e9c923206ffec0d Mon Sep 17 00:00:00 2001 From: Shankar Konar <konar.shankar2013@gmail.com> Date: Mon, 10 Feb 2020 11:29:00 +0530 Subject: [PATCH 562/666] code cleanup --- .../tests/app/code/Magento/Ui/base/js/grid/data-storage.test.js | 2 -- 1 file changed, 2 deletions(-) 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 4fe7aff69d0e2..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 @@ -5,8 +5,6 @@ /*eslint max-nested-callbacks: 0*/ /*jscs:disable requireCamelCaseOrUpperCaseIdentifiers*/ -/*eslint newline-after-var: ["error", "always"]*/ -/*eslint-env es6*/ define([ 'jquery', 'Magento_Ui/js/grid/data-storage' From 435c3fe27964a15729ecbc2ebbafe04b34412faf Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 10 Feb 2020 09:42:21 +0200 Subject: [PATCH 563/666] remove fixtures after test --- .../Magento/Ui/base/js/modal/modal.test.js | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) 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 ccfad86c6cfb0..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 @@ -11,13 +11,24 @@ define([ describe('ui/js/modal/modal', function () { - var element = $('<div>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>'); + $(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(); @@ -32,12 +43,12 @@ define([ expect($(modal).length).toEqual(1); }); - it('Verify setTitle() method set title', function () { + 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(2); + expect($(modal.options.modalTitle).find(modal.options.modalSubTitle).length).toBe(1); }); }); }); From f755b429c8022b8a2b03a5c9da0aea5100c90d41 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Mon, 10 Feb 2020 09:43:47 +0200 Subject: [PATCH 564/666] MC-30650: [Magento Cloud] Customer Creation - The store view is not in the associated website --- app/code/Magento/Customer/i18n/en_US.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index a70aa08dba735..0bcd5ce27dbb5 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -540,3 +540,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." From 959e5e260532f1fbebd37830921e8bdb52339e93 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Feb 2020 10:28:59 +0200 Subject: [PATCH 565/666] MC-31262: Storefront: Reset/Forgot customer password --- .../Block/Account/ResetPasswordTest.php | 86 +++++++++++ .../Customer/Controller/AccountTest.php | 79 ---------- .../Controller/CreatePasswordTest.php | 98 +++++++++++++ .../Controller/ForgotPasswordPostTest.php | 137 ++++++++++++++++++ .../AccountManagement/ForgotPasswordTest.php | 64 ++++++++ 5 files changed, 385 insertions(+), 79 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Block/Account/ResetPasswordTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/ForgotPasswordPostTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagement/ForgotPasswordTest.php 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/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index df4acf3acca91..18f9b2d2cb737 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -132,35 +132,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 +368,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 */ 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..9ad25ae5ddd5f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php @@ -0,0 +1,98 @@ +<?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/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)); + } +} From 8641b01b70a7d1b86c1b74548cd62e2e84027e60 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 10 Feb 2020 00:31:21 -0800 Subject: [PATCH 566/666] MC-25260: A wrong behaviour of a chart order --- app/code/Magento/Backend/Block/Dashboard/Graph.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php index 145c3394efd7b..527bb2136b4c5 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Graph.php +++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php @@ -234,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'); From f7827c90528f2118041a8ef139da8d30823b3161 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 10 Feb 2020 10:32:46 +0200 Subject: [PATCH 567/666] MC-31264: Storefront: View bundle product on storefront --- .../Bundle/Model/PrepareBundleLinks.php | 89 ++++++++ .../Type/AbstractBundleOptionsViewTest.php | 194 +++++++++++++++++ .../Catalog/Product/View/Type/BundleTest.php | 203 ++++++++++++++---- .../View/Type/CheckboxOptionViewTest.php | 77 +++++++ .../View/Type/DropDownOptionViewTest.php | 77 +++++++ .../View/Type/MultiselectOptionViewTest.php | 77 +++++++ .../Product/View/Type/RadioOptionViewTest.php | 73 +++++++ .../bundle_product_checkbox_options.php | 77 +++++++ ...ndle_product_checkbox_options_rollback.php | 27 +++ ...undle_product_checkbox_required_option.php | 68 ++++++ ...duct_checkbox_required_option_rollback.php | 26 +++ ...ndle_product_checkbox_required_options.php | 76 +++++++ ...uct_checkbox_required_options_rollback.php | 27 +++ .../bundle_product_dropdown_options.php | 76 +++++++ ...ndle_product_dropdown_options_rollback.php | 27 +++ ...ndle_product_dropdown_required_options.php | 76 +++++++ ...uct_dropdown_required_options_rollback.php | 27 +++ .../bundle_product_multiselect_options.php | 76 +++++++ ...e_product_multiselect_options_rollback.php | 27 +++ ...le_product_multiselect_required_option.php | 68 ++++++ ...t_multiselect_required_option_rollback.php | 26 +++ ...e_product_multiselect_required_options.php | 76 +++++++ ..._multiselect_required_options_rollback.php | 27 +++ .../_files/bundle_product_radio_options.php | 76 +++++++ .../bundle_product_radio_options_rollback.php | 27 +++ .../bundle_product_radio_required_option.php | 68 ++++++ ...product_radio_required_option_rollback.php | 26 +++ .../bundle_product_radio_required_options.php | 77 +++++++ ...roduct_radio_required_options_rollback.php | 27 +++ 29 files changed, 1860 insertions(+), 38 deletions(-) create mode 100644 dev/tests/integration/framework/Magento/TestFramework/Bundle/Model/PrepareBundleLinks.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/AbstractBundleOptionsViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/CheckboxOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/DropDownOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/MultiselectOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Block/Catalog/Product/View/Type/RadioOptionViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_checkbox_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_dropdown_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_multiselect_required_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_options_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_option_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_radio_required_options_rollback.php 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/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/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/_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..f9636890e61f6 --- /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') + ->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..453b531f75b2d --- /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') + ->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..9b84d1236c5c9 --- /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') + ->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..06f6473802ee2 --- /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') + ->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..1789f472f968d --- /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') + ->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..a5667b89f8bf4 --- /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') + ->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..7789045f6f7ef --- /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') + ->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..65bb49f3b6122 --- /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') + ->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..def31b48b2172 --- /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') + ->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..c659387e09dcc --- /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') + ->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..ec28bf556b69c --- /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') + ->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); From 4853eea8f16526dfbbbcfb96793632f18ef69031 Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Mon, 10 Feb 2020 10:45:35 +0100 Subject: [PATCH 568/666] Cast $attributeId as int in select --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index e50abbc11e54a..9ee6d36824141 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -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(); } From 1e6f8bc6a811074fe8b504fc60ea3f05fce94e24 Mon Sep 17 00:00:00 2001 From: Andrii Meysar <andrii.meysar@transoftgroup.com> Date: Mon, 10 Feb 2020 12:27:51 +0200 Subject: [PATCH 569/666] MC-16249: [CLOUD] Attachment is not opened on storefront --- .../Model/App/Response/HttpPlugin.php | 9 +- .../Model/App/Response/HttpPluginTest.php | 113 ++++++++---------- .../Php/_files/phpstan/blacklist/common.txt | 1 - 3 files changed, 56 insertions(+), 67 deletions(-) diff --git a/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php b/app/code/Magento/PageCache/Model/App/Response/HttpPlugin.php index 7a3b9055d0d12..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,12 +17,12 @@ 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 || headers_sent()) { + if ($subject instanceof NotCacheableInterface || $subject->headersSent()) { return; } 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 5b5fa1f0ff12a..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,76 +3,63 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -// @codingStandardsIgnoreStart -namespace Magento\PageCache\Model\App\Response { - $mockPHPFunctions = false; +namespace Magento\PageCache\Test\Unit\Model\App\Response; - function headers_sent() - { - global $mockPHPFunctions; - if ($mockPHPFunctions) { - return false; - } - - return call_user_func_array('\headers_sent', func_get_args()); - } -} - -namespace Magento\PageCache\Test\Unit\Model\App\Response { - - use Magento\Framework\App\Response\Http; - use Magento\MediaStorage\Model\File\Storage\Response; - use Magento\PageCache\Model\App\Response\HttpPlugin; +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; - // @codingStandardsIgnoreEnd +/** + * Tests \Magento\PageCache\Model\App\Response\HttpPlugin. + */ +class HttpPluginTest extends TestCase +{ + /** + * @var HttpPlugin + */ + private $httpPlugin; - class HttpPluginTest extends \PHPUnit\Framework\TestCase + /** + * @inheritdoc + */ + protected function setUp() { - /** - * @inheritdoc - */ - protected function setUp() - { - global $mockPHPFunctions; - $mockPHPFunctions = true; - } + parent::setUp(); + $this->httpPlugin = new HttpPlugin(); + } - /** - * @inheritdoc - */ - protected function tearDown() - { - global $mockPHPFunctions; - $mockPHPFunctions = false; - } + /** + * @param string $responseClass + * @param bool $headersSent + * @param int $sendVaryCalled + * @return void + * + * @dataProvider beforeSendResponseDataProvider + */ + public function testBeforeSendResponse(string $responseClass, bool $headersSent, int $sendVaryCalled): void + { + /** @var HttpResponse|MockObject $responseMock */ + $responseMock = $this->createMock($responseClass); + $responseMock->expects($this->any())->method('headersSent')->willReturn($headersSent); + $responseMock->expects($this->exactly($sendVaryCalled))->method('sendVary'); - /** - * @param string $responseInstanceClass - * @param int $sendVaryCalled - * @return void - * - * @dataProvider beforeSendResponseDataProvider - */ - public function testBeforeSendResponse(string $responseInstanceClass, int $sendVaryCalled): void - { - /** @var Http | \PHPUnit_Framework_MockObject_MockObject $responseMock */ - $responseMock = $this->createMock($responseInstanceClass); - $responseMock->expects($this->exactly($sendVaryCalled)) - ->method('sendVary'); - $plugin = new HttpPlugin(); - $plugin->beforeSendResponse($responseMock); - } + $this->httpPlugin->beforeSendResponse($responseMock); + } - /** - * @return array - */ - public function beforeSendResponseDataProvider(): array - { - return [ - [Http::class, 1], - [Response::class, 0] - ]; - } + /** + * @return array + */ + public function beforeSendResponseDataProvider(): array + { + return [ + '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/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt index 5066040e484cb..f54defbd57604 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpstan/blacklist/common.txt @@ -14,4 +14,3 @@ dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressRepositoryTest.ph dev/tests/api-functional/testsuite/Magento/Framework/Model/Entity/HydratorTest.php dev/tests/api-functional/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php dev/tests/api-functional/testsuite/Magento/Integration/Model/CustomerTokenServiceTest.php -app/code/Magento/PageCache/Test/Unit/Model/App/Response/HttpPluginTest.php From 997a0de132e38cc4bf4e0d94a9f65dbbc5b30bc5 Mon Sep 17 00:00:00 2001 From: Adarsh Manickam <adarsh.apple@icloud.com> Date: Mon, 10 Feb 2020 17:03:30 +0530 Subject: [PATCH 570/666] Deprecated associated integration test class --- .../Sales/Model/Order/Email/Sender/ShipmentSenderTest.php | 3 +++ 1 file changed, 3 insertions(+) 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 { From c5cbcfe14a9b3019ae3f4470e857176ddbaa54f0 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Mon, 10 Feb 2020 14:57:03 +0200 Subject: [PATCH 571/666] MC-24466: Unable to use API to save quote item when backorder is set to "Allowed and Notify Customer" --- .../Model/Quote/Item/CartItemPersister.php | 16 ++-- .../Quote/Api/GuestCartItemRepositoryTest.php | 73 ++++++++++++++++++- 2 files changed, 83 insertions(+), 6 deletions(-) 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/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); + } + } } From 313e6b2c4caa8f07a72eba843925489b2b33e366 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Mon, 10 Feb 2020 15:25:28 +0200 Subject: [PATCH 572/666] MC-31083: [FT] [MFTF] Fix test AdminCreateImageSwatchTest - delete created swatch attribute in after --- .../AdminDeleteProductAttributeByLabelActionGroup.xml | 2 +- .../Test/Mftf/Test/AdminCreateImageSwatchTest.xml | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml index 21cc90ba4b4e8..7b453735994d7 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminDeleteProductAttributeByLabelActionGroup.xml @@ -13,7 +13,7 @@ <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"/> + <argument name="productAttributeLabel" type="string" defaultValue="{{ProductAttributeFrontendLabel.label}}"/> </arguments> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml index 372df5bd3acee..d2352b9efa134 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateImageSwatchTest.xml @@ -27,9 +27,7 @@ <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> <argument name="sku" value="{{BaseConfigurableProduct.sku}}"/> </actionGroup> - <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"> - <argument name="productAttributeLabel" value="{{ProductAttributeFrontendLabel.label}}"/> - </actionGroup> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteProductAttribute"/> <actionGroup ref="NavigateToAndResetProductAttributeGridToDefaultViewActionGroup" stepKey="resetProductAttributeFilters"/> <actionGroup ref="logout" stepKey="logoutFromAdmin"/> </after> @@ -107,7 +105,7 @@ <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"/> @@ -147,7 +145,7 @@ </assertContains> <!-- Go to the product listing page and see text swatch options --> - <amOnPage url="$$createCategory.custom_attributes[url_key]$$.html" stepKey="goToCategoryPageStorefront"/> + <amOnPage url="$createCategory.custom_attributes[url_key]$.html" stepKey="goToCategoryPageStorefront"/> <waitForPageLoad stepKey="waitForProductListingPage"/> <!-- Verify the storefront --> From 3eb92f5e8346a9fdbc22ed8a87a404130858d16b Mon Sep 17 00:00:00 2001 From: Lukasz Bajsarowicz <lukasz.bajsarowicz@gmail.com> Date: Mon, 10 Feb 2020 14:27:35 +0100 Subject: [PATCH 573/666] Reindex after saving product changes --- .../AdminCreateDownloadableProductWithCustomOptionsTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml index fb5983bb58b6d..3651b322628c4 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithCustomOptionsTest.xml @@ -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"/> From 68b06de07437de32e94d94d9a7851996c4c5eb45 Mon Sep 17 00:00:00 2001 From: Grayson <grayson@astralwebinc.com> Date: Mon, 10 Feb 2020 22:00:00 +0800 Subject: [PATCH 574/666] fix wrong : --- app/code/Magento/Bundle/Helper/Data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Helper/Data.php b/app/code/Magento/Bundle/Helper/Data.php index 3997cac4e0c8d..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 $configData['allowed_selection_types'] ?? : []; + return $configData['allowed_selection_types'] ?? []; } } From 262280d869aaf63005aff6074b0ff9c932fe8555 Mon Sep 17 00:00:00 2001 From: Krissy Hiserote <khiserote@magento.com> Date: Mon, 10 Feb 2020 08:42:19 -0600 Subject: [PATCH 575/666] MC-30236: Upgrade from 2.3.x CE with SD to 2.3.x EE AreaCode Exception - fix unit test --- setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index d087162f9b06e..2b992c30615c2 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -309,7 +309,7 @@ public function testInstall(array $request, array $logMessages) $cacheManager->expects($this->any())->method('getAvailableTypes')->willReturn(['foo', 'bar']); $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([]); + $cacheManager->expects($this->exactly(3))->method('getStatus')->willReturn(['foo' => 1, 'bar' => 1]); $appState = $this->getMockBuilder(\Magento\Framework\App\State::class) ->disableOriginalConstructor() ->disableArgumentCloning() @@ -412,7 +412,7 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [print_r([], true)], + [print_r(['foo' => 1, 'bar' => 1], true)], ['Installing data...'], ['Data install/update:'], ['Disabling caches:'], @@ -463,7 +463,7 @@ public function installDataProvider() ['Installing user configuration...'], ['Enabling caches:'], ['Current status:'], - [print_r([], true)], + [print_r(['foo' => 1, 'bar' => 1], true)], ['Installing data...'], ['Data install/update:'], ['Disabling caches:'], From 15492aa2be888f248946680f548a9a422f34db3a Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 10 Feb 2020 16:44:48 +0200 Subject: [PATCH 576/666] MC-31308: [2.4] Test AdminSaveAndCloseCmsBlockTest flaky on Jenkins --- .../Test/Mftf/ActionGroup/LoginActionGroup.xml | 3 ++- ...ndCloseCMSBlockWithSplitButtonActionGroup.xml | 3 ++- .../VerifyCmsBlockSaveSplitButtonActionGroup.xml | 1 + .../Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml | 16 ++++++++++------ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml index 7068478bb4790..8f61a0a06dd5e 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/LoginActionGroup.xml @@ -10,7 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="LoginActionGroup"> <annotations> - <description>Login to Backend Admin using ENV Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description> + <description>DEPRECATED. Please use LoginAsAdmin instead. + Login to Backend Admin using ENV Admin credentials. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description> </annotations> <amOnPage url="{{_ENV.MAGENTO_BACKEND_NAME}}" stepKey="navigateToAdmin"/> 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/AdminSaveAndCloseCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminSaveAndCloseCmsBlockTest.xml index 8c89c47ab5077..23f602d7b1005 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="logout" 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> From fda86a8c5e8472335078a77fc042a38dc46e5d2f Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 10 Feb 2020 17:33:27 +0200 Subject: [PATCH 577/666] MC-30720: [MFTF] [2.4] Fix flaky test AdminMoveAnchoredCategoryTest (MAGETWO-76273) --- .../Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml index 7261df8765dc5..f01becd2034d8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMoveAnchoredCategoryTest.xml @@ -55,7 +55,7 @@ <argument name="parentCategory" value="$simpleSubCategoryTwo.name$"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageFirst"/> + <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"/> @@ -97,7 +97,7 @@ <argument name="parentCategory" value="Default Category"/> </actionGroup> <!--Verify that navigation menu categories level is correct--> - <amOnPage url="{{StorefrontHomePage.url}}" stepKey="openHomePageSecond"/> + <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"/> From bf21c4bea3cbd600ee1333186bf43b3065847681 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 01:56:16 +0530 Subject: [PATCH 578/666] covered untit & updated loadcssasync format --- .../Controller/Result/AsyncCssPlugin.php | 4 +- .../Controller/Result/AsyncCssPluginTest.php | 143 ++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index f0c343c366abc..9dbb92d51067b 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -16,7 +16,7 @@ */ class AsyncCssPlugin { - private const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; /** * @var ScopeConfigInterface @@ -60,7 +60,7 @@ function ($matches) use (&$cssMatches) { $loadCssAsync = sprintf( '<link rel="preload" as="style" media="%s"' . ' onload="this.onload=null;this.rel=\'stylesheet\'"' . - ' href="%s">', + ' href="%s" />', $media, $href ); 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..98321976767e2 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -0,0 +1,143 @@ +<?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 +{ + /** + * @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 void + */ + public function sendResponseDataProvider() + { + 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( + AsyncCssPlugin::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( + AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + ScopeInterface::SCOPE_STORE + ) + ->willReturn(false); + + $this->plugin->beforeSendResponse($this->httpMock); + } +} From 2397bec2b774ba9f6007f962ea9bf620043cfba6 Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Mon, 10 Feb 2020 21:30:52 +0100 Subject: [PATCH 579/666] Unit test added --- .../Entity/Collection/AbstractCollection.php | 6 +-- .../Collection/AbstractCollectionStub.php | 10 ++++ .../Collection/AbstractCollectionTest.php | 48 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 9ee6d36824141..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; } 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..d3e8ce29cbc61 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 @@ -12,6 +12,10 @@ */ 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 +109,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 +217,30 @@ 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 */ From 2881e4886fee787e5ecdf73edef4a197321bea43 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 02:02:20 +0530 Subject: [PATCH 580/666] PHPdoc updated --- .../Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php index 98321976767e2..6f9cd56c3c5c9 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -59,9 +59,9 @@ protected function setUp(): void /** * Data Provider for before send response * - * @return void + * @return array */ - public function sendResponseDataProvider() + public function sendResponseDataProvider(): array { return [ [ From 1e50859a6c2f52984a9a2812fb6c93aa6b0a0f34 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 10:02:22 +0530 Subject: [PATCH 581/666] Stub constant updated --- app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php | 2 +- .../Test/Unit/Controller/Result/AsyncCssPluginTest.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php index 9dbb92d51067b..70ea478004b9d 100644 --- a/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php +++ b/app/code/Magento/Theme/Controller/Result/AsyncCssPlugin.php @@ -16,7 +16,7 @@ */ class AsyncCssPlugin { - const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + private const XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; /** * @var ScopeConfigInterface diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php index 6f9cd56c3c5c9..b1303e991a680 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/AsyncCssPluginTest.php @@ -20,6 +20,8 @@ */ class AsyncCssPluginTest extends TestCase { + const STUB_XML_PATH_USE_CSS_CRITICAL_PATH = 'dev/css/use_css_critical_path'; + /** * @var AsyncCssPlugin */ @@ -107,7 +109,7 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void $this->scopeConfigMock->expects($this->once()) ->method('isSetFlag') ->with( - AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, ScopeInterface::SCOPE_STORE ) ->willReturn($isSetFlag); @@ -133,7 +135,7 @@ public function testIfGetContentIsNotAString(): void $this->scopeConfigMock->expects($this->any()) ->method('isSetFlag') ->with( - AsyncCssPlugin::XML_PATH_USE_CSS_CRITICAL_PATH, + self::STUB_XML_PATH_USE_CSS_CRITICAL_PATH, ScopeInterface::SCOPE_STORE ) ->willReturn(false); From e61a52feee7fe7401dc01ae48deda04b4024c078 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 11 Feb 2020 11:41:44 +0200 Subject: [PATCH 582/666] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...ertStorefrontProductPriceInCategoryPageActionGroup.xml | 1 - ...efrontProductSpecialPriceInCategoryPageActionGroup.xml | 2 +- .../Mftf/Section/StorefrontCategoryProductSection.xml | 2 +- ...GroupMembershipArePersistedUnderLongTermCookieTest.xml | 8 +++----- .../AssertDefaultWelcomeMessageActionGroup.xml | 4 ++-- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml index e6eb475153f1f..87f6e6e705263 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductPriceInCategoryPageActionGroup.xml @@ -18,7 +18,6 @@ <argument name="productPrice" type="string" defaultValue="{{productWithHTMLEntityOne.price}}"/> </arguments> - <!-- Go to storefront category page, assert product visibility --> <amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="navigateToCategoryPage"/> <waitForPageLoad stepKey="waitForProductPageLoad"/> <see userInput="{{productPrice}}" selector="{{StorefrontCategoryProductSection.ProductPriceByName(productName)}}" stepKey="assertProductPrice"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml index 17c9e43e15fa7..c449089dab264 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -10,7 +10,7 @@ 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 is present and correct.</description> + <description>Goes to Storefront Category page for the provided Category. Validates that the Product price and special price is correct.</description> </annotations> <arguments> <argument name="productSpecialPrice" type="string" defaultValue="{{updateVirtualProductSpecialPrice.special_price}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 12fd350612d7d..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="//main//li[.//a[contains(text(), '{{productName}}')]]//span[@class='special-price']/span" 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/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index 65a0e30e17b37..102054c315f4c 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -25,9 +25,7 @@ <createData entity="productWithHTMLEntityOne" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </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"/> @@ -46,7 +44,7 @@ <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="clickSaveAndApplyRule"/> <!-- Perform reindex --> - <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> + <magentoCLI command="indexer:reindex" arguments="catalogrule_rule" stepKey="reindex"/> </before> <after> <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> @@ -94,7 +92,7 @@ <!--Click the *Not you?* link and check the price for Simple Product--> <click selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="clickNotYouLink"/> - <actionGroup ref="AssertDefaultWelcomeMessageActionGroup" stepKey="seeWelcomeMessageForJohnDoeCustomerAfterLogout"/> + <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$"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml index 05414fb8ebe20..eb66cafe43dd3 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml @@ -8,12 +8,12 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertDefaultWelcomeMessageActionGroup"> + <actionGroup name="AssertStorefrontDefaultWelcomeMessageActionGroup"> <annotations> <description>Validates that the Welcome message is present and correct and not you link absent.</description> </annotations> - <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForElementVisible selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="waitDefaultMessage"/> <see userInput="Default welcome msg!" selector="{{StorefrontPanelHeaderSection.WelcomeMessage}}" stepKey="verifyDefaultMessage"/> <dontSeeElement selector="{{StorefrontPanelHeaderSection.notYouLink}}" stepKey="checkAbsenceLinkNotYou"/> </actionGroup> From a7a25ef17b0c636b7e68b3e24de2dc1533a53aac Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 11 Feb 2020 12:49:45 +0200 Subject: [PATCH 583/666] MC-31369: [2.4] Test CreateCompanyWithOptionalRegionTest fail on Jenkins (MAGETWO-94110) --- .../Data/GeneralStateOptionsConfigData.xml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/code/Magento/Directory/Test/Mftf/Data/GeneralStateOptionsConfigData.xml 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> From 5f02e44917e639406c531cef6d8b907ac43a83fd Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 11 Feb 2020 12:53:57 +0200 Subject: [PATCH 584/666] MC-31157: Error on Place order with Braintree and 3d-secure. Address validation --- .../frontend/web/js/view/payment/3d-secure.js | 21 ++++++++++++++++++- .../view/payment/method-renderer/cc-form.js | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) 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; From 343ea61890663fe537d34296750fb6d9bfbd64f5 Mon Sep 17 00:00:00 2001 From: Bohdan Shevchenko <1408sheva@gmail.com> Date: Tue, 11 Feb 2020 14:24:52 +0200 Subject: [PATCH 585/666] MC-24236: [MFTF Test] Unskip MFTF test MC-13607 "Verify that Catalog Price Rule and Customer Group Membership are persisted under long-term cookie" --- ...rtStorefrontProductSpecialPriceInCategoryPageActionGroup.xml | 2 +- ...xml => AssertStorefrontDefaultWelcomeMessageActionGroup.xml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename app/code/Magento/Customer/Test/Mftf/ActionGroup/{AssertDefaultWelcomeMessageActionGroup.xml => AssertStorefrontDefaultWelcomeMessageActionGroup.xml} (100%) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml index c449089dab264..b2a7d5f96ec94 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductSpecialPriceInCategoryPageActionGroup.xml @@ -10,7 +10,7 @@ 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 is correct.</description> + <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}}"/> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml similarity index 100% rename from app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertDefaultWelcomeMessageActionGroup.xml rename to app/code/Magento/Customer/Test/Mftf/ActionGroup/AssertStorefrontDefaultWelcomeMessageActionGroup.xml From 5d0dfb541ac9739e14de7047ad318b89ce9aea17 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Tue, 11 Feb 2020 15:26:36 +0200 Subject: [PATCH 586/666] Unit Test for \Magento\Directory\Block\Adminhtml\Frontend\Currency\Base --- .../Adminhtml/Frontend/Currency/BaseTest.php | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 app/code/Magento/Directory/Test/Unit/Block/Adminhtml/Frontend/Currency/BaseTest.php 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.'); + } +} From 2d19477ebf398f066930ac413e6e4ebec6ce1830 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Tue, 11 Feb 2020 17:00:37 +0200 Subject: [PATCH 587/666] fix static, fix conflict merge --- .../Magento/Catalog/Model/Product/Copier.php | 25 ++- .../Test/Unit/Model/Product/CopierTest.php | 174 +++++++++++------- 2 files changed, 118 insertions(+), 81 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php index 645977a35af1f..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,20 +74,17 @@ 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); @@ -96,11 +95,11 @@ public function copy(Product $product) $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); @@ -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/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php index 18179489fbd94..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,53 +3,66 @@ * 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; @@ -58,27 +71,23 @@ class CopierTest extends \PHPUnit\Framework\TestCase */ 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, @@ -89,9 +98,12 @@ protected function setUp() } /** + * Test duplicate product + * + * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function testCopy() + public function testCopy(): void { $stockItem = $this->createMock(StockItemInterface::class); $extensionAttributes = $this->getMockBuilder(ProductExtension::class) @@ -110,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, @@ -126,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, @@ -139,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, @@ -176,51 +194,71 @@ public function testCopy() 'getStoreIds', 'setMetaTitle', 'setMetaKeyword', - 'setMetaDescription' + '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->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->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(StockItemInterface::class) ->getMock(); From b4390ed4e68052b83f4551369a5ffca5e8f7be46 Mon Sep 17 00:00:00 2001 From: Arnob Saha <arnobsh@gmail.com> Date: Thu, 31 Oct 2019 13:57:20 -0500 Subject: [PATCH 588/666] MC-21501: Investigation of stock quantity calculation for Configurable Products - check $product is an instance of Product before processing --- .../Layer/Filter/_files/attribute_with_option_rollback.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); } } From 6220474bbc24e141690705134c9c66e27c94cba9 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Tue, 11 Feb 2020 22:21:31 +0530 Subject: [PATCH 589/666] [Theme] Covered Unit Test for \Magento\Theme\controller\Result\JsFooterPlugin --- .../Controller/Result/JsFooterPluginTest.php | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php 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..a604aaf10aeb7 --- /dev/null +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.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\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 beforeSendResponse() + * + * @return array + */ + public function sendResponseDataProvider(): array + { + return [ + [ + "content" => "<body><h1>Test Title</h1>" . + "<script text=\"text/javascript\">test</script>" . + "<script text=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p></body>", + "flag" => true, + "result" => "<body><h1>Test Title</h1>" . + "<script text=\"text/x-magento-template\">test</script>" . + "<p>Test Content</p>" . + "<script text=\"text/javascript\">test</script>" . + "\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>\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); + } + + /** + * Test BeforeSendResponse if content is not a string + * + * @return void + */ + public function testBeforeSendResponseIfGetContentIsNotAString(): void + { + $this->httpMock->expects($this->once()) + ->method('getContent') + ->willReturn([]); + + $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); + } +} From a2082260635fea744e8a9e9258e4b7f1ffcae06c Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 01:11:03 +0530 Subject: [PATCH 590/666] Test case updated with if content NULL & fixed health check issue --- .../Controller/Result/JsFooterPluginTest.php | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index a604aaf10aeb7..3d6bf010d4207 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -59,7 +59,7 @@ protected function setUp(): void } /** - * Data Provider for beforeSendResponse() + * Data Provider for testBeforeSendResponse() * * @return array */ @@ -68,14 +68,14 @@ public function sendResponseDataProvider(): array return [ [ "content" => "<body><h1>Test Title</h1>" . - "<script text=\"text/javascript\">test</script>" . - "<script text=\"text/x-magento-template\">test</script>" . + "<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 text=\"text/x-magento-template\">test</script>" . + "<script type=\"text/x-magento-template\">test</script>" . "<p>Test Content</p>" . - "<script text=\"text/javascript\">test</script>" . + "<script type=\"text/x-magento-init\">test</script>" . "\n</body>" ], [ @@ -121,16 +121,35 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void $this->plugin->beforeSendResponse($this->httpMock); } + /** + * Data Provider for testBeforeSendResponseIfGetContentIsNotAString() + * + * @return array + */ + public function ifGetContentIsNotAStringDataProvider(): array + { + return [ + [ + 'content' => [] + ], + [ + 'content' => NULL + ] + ]; + } + /** * Test BeforeSendResponse if content is not a string * + * @param string $content * @return void + * @dataProvider ifGetContentIsNotAStringDataProvider */ - public function testBeforeSendResponseIfGetContentIsNotAString(): void + public function testBeforeSendResponseIfGetContentIsNotAString($content): void { $this->httpMock->expects($this->once()) ->method('getContent') - ->willReturn([]); + ->willReturn($content); $this->scopeConfigMock->expects($this->never()) ->method('isSetFlag') From a0ed3182c71af73fc7ad2168d7ee9631845b1611 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Tue, 11 Feb 2020 13:55:04 -0600 Subject: [PATCH 591/666] MQE-1987: Bump MFTF version and deliver Magento branches Updated with mainline + version bump to 2.6.1 --- composer.json | 2 +- composer.lock | 164 ++++++++++++++++++++++++++------------------------ 2 files changed, 87 insertions(+), 79 deletions(-) diff --git a/composer.json b/composer.json index 577987067dc76..1e38c3c13601d 100644 --- a/composer.json +++ b/composer.json @@ -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.6.0", + "magento/magento2-functional-testing-framework": "2.6.1", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index dd59126b96caa..be50d79e33eff 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": "27452593216dfff37ed2a7f2aea0237c", + "content-hash": "fed60ae2b1869a71f2068e4f55a8695f", "packages": [ { "name": "braintree/braintree_php", @@ -1850,6 +1850,11 @@ "MIT" ], "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1857,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).", @@ -6675,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", @@ -7442,16 +7381,16 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262" + "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", - "reference": "3609f4fa57c6e9a2ee7c3d3b7c0f02e9becd8262", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/f56c5563ae23be5abac779a97f6d75cdf505d0a2", + "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2", "shasum": "" }, "require": { @@ -7470,9 +7409,13 @@ "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", @@ -7519,7 +7462,7 @@ "magento", "testing" ], - "time": "2020-02-05T15:53:02+00:00" + "time": "2020-02-11T19:46:39+00:00" }, { "name": "mikey179/vfsstream", @@ -7911,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", @@ -8209,20 +8217,20 @@ "authors": [ { "name": "Manuel Pichler", - "role": "Project Founder", "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler" + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" }, { "name": "Marc Würth", - "role": "Project Maintainer", "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84" + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" }, { "name": "Other contributors", - "role": "Contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors" + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" } ], "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", From 6a82bf788cc9c82449cd8f40e859b7712a24a2c1 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 01:51:31 +0530 Subject: [PATCH 592/666] Data Provider keys added with description --- .../Test/Unit/Controller/Result/JsFooterPluginTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index 3d6bf010d4207..42e9646314ff1 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -66,7 +66,7 @@ protected function setUp(): void 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>" . @@ -78,12 +78,12 @@ public function sendResponseDataProvider(): array "<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>" @@ -129,10 +129,10 @@ public function testBeforeSendResponse($content, $isSetFlag, $result): void public function ifGetContentIsNotAStringDataProvider(): array { return [ - [ + 'empty_array' => [ 'content' => [] ], - [ + 'null' => [ 'content' => NULL ] ]; From a017a64f3dc2bc44876862d72c1da8f8f83d896b Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Tue, 11 Feb 2020 16:33:28 -0600 Subject: [PATCH 593/666] MQE-1987: Bump MFTF version and deliver Magento branches Updated with mainline + version bump to 2.6.1 --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index be50d79e33eff..9620c73c90ba4 100644 --- a/composer.lock +++ b/composer.lock @@ -7385,12 +7385,12 @@ "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2" + "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/f56c5563ae23be5abac779a97f6d75cdf505d0a2", - "reference": "f56c5563ae23be5abac779a97f6d75cdf505d0a2", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/b00f5e195e1ed7f6335bce3052be9a0291f4d0db", + "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db", "shasum": "" }, "require": { @@ -7462,7 +7462,7 @@ "magento", "testing" ], - "time": "2020-02-11T19:46:39+00:00" + "time": "2020-02-11T22:23:54+00:00" }, { "name": "mikey179/vfsstream", From c9dcd277bf1a7a41e78aeae3d775b4cee258a7cb Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Wed, 12 Feb 2020 09:13:37 +0530 Subject: [PATCH 594/666] Fixed static test --- .../Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php index 42e9646314ff1..8b696251d4e73 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/JsFooterPluginTest.php @@ -133,7 +133,7 @@ public function ifGetContentIsNotAStringDataProvider(): array 'content' => [] ], 'null' => [ - 'content' => NULL + 'content' => null ] ]; } From b35afbe512e66239cb3539e94f31bd98032b1b8d Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 12 Feb 2020 12:42:56 +0200 Subject: [PATCH 595/666] magento/magento2#: GraphQL. MergeCarts mutation. Add additional API-functional test cases --- .../GraphQl/Quote/Customer/MergeCartsTest.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) 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 * From a0e239a9fa8ce3ebc2a392b7a16442a24677ffdb Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 12 Feb 2020 13:06:59 +0200 Subject: [PATCH 596/666] Unit test for Magento\Downloadable\Model\Sample\DeleteHandler --- .../Unit/Model/Sample/DeleteHandlerTest.php | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 app/code/Magento/Downloadable/Test/Unit/Model/Sample/DeleteHandlerTest.php 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)); + } +} From f58ddb5b2996d4069a0c79bf693d7f92bbb2e5e5 Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 12 Feb 2020 14:43:40 +0200 Subject: [PATCH 597/666] MC-30675: [API] Product async bulk API endpoint is adding additional fields to DB --- .../Product/Webapi/ProductOutputProcessor.php | 101 +++++ .../Webapi/ProductOutputProcessorTest.php | 350 ++++++++++++++++++ .../Magento/Catalog/etc/webapi_rest/di.xml | 12 + .../Magento/Catalog/etc/webapi_soap/di.xml | 12 + .../Api/ProductRepositoryInterfaceTest.php | 18 +- .../Api/ProductRepositoryInterfaceTest.php | 1 - 6 files changed, 482 insertions(+), 12 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Product/Webapi/ProductOutputProcessor.php create mode 100644 app/code/Magento/Catalog/Test/Unit/Model/Product/Webapi/ProductOutputProcessorTest.php 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/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/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/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/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() From 511e16a3ce006cb31621cb9b87cd576f0304c62b Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 12 Feb 2020 14:59:27 +0200 Subject: [PATCH 598/666] refactor cover changes with unit test --- .../Customer/Model/Account/Redirect.php | 33 ++-- .../Test/Unit/Model/Account/RedirectTest.php | 182 +++++++++++++----- app/code/Magento/Customer/etc/di.xml | 0 3 files changed, 150 insertions(+), 65 deletions(-) mode change 100755 => 100644 app/code/Magento/Customer/Model/Account/Redirect.php mode change 100755 => 100644 app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php mode change 100755 => 100644 app/code/Magento/Customer/etc/di.xml diff --git a/app/code/Magento/Customer/Model/Account/Redirect.php b/app/code/Magento/Customer/Model/Account/Redirect.php old mode 100755 new mode 100644 index ba1f72369f606..0389a380b36dc --- a/app/code/Magento/Customer/Model/Account/Redirect.php +++ b/app/code/Magento/Customer/Model/Account/Redirect.php @@ -7,19 +7,19 @@ 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 @@ -298,11 +298,14 @@ public function getRedirectCookie() */ public function setRedirectCookie($route) { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setHttpOnly(true) - ->setDuration(3600) - ->setPath($this->storeManager->getStore()->getStorePath()); - $this->getCookieManager()->setPublicCookie(self::LOGIN_REDIRECT_URL, $route, $cookieMetadata); + $this->getCookieManager()->setPublicCookie( + self::LOGIN_REDIRECT_URL, + $route, + $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setHttpOnly(true) + ->setDuration(3600) + ->setPath($this->storeManager->getStore()->getStorePath()) + ); } /** @@ -314,8 +317,10 @@ public function setRedirectCookie($route) */ public function clearRedirectCookie() { - $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() - ->setPath($this->storeManager->getStore()->getStorePath()); - $this->getCookieManager()->deleteCookie(self::LOGIN_REDIRECT_URL, $cookieMetadata); + $this->getCookieManager()->deleteCookie( + self::LOGIN_REDIRECT_URL, + $this->cookieMetadataFactory->createPublicCookieMetadata() + ->setPath($this->storeManager->getStore()->getStorePath()) + ); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php old mode 100755 new mode 100644 index f520182e51199..5c57012e0505c --- a/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Account/RedirectTest.php @@ -8,18 +8,22 @@ namespace Magento\Customer\Test\Unit\Model\Account; -use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory; 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 @@ -27,74 +31,76 @@ 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 CookieMetadataFactory | \PHPUnit_Framework_MockObject_MockObject + * @var CookieMetadataFactory|MockObject */ protected $cookieMetadataFactory; /** - * @var HostChecker | \PHPUnit_Framework_MockObject_MockObject + * @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( @@ -117,44 +123,27 @@ protected function setUp() ->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->cookieMetadataFactory = $this->getMockBuilder(CookieMetadataFactory::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, @@ -174,6 +163,8 @@ protected function setUp() } /** + * Verify get redirect method + * * @param int $customerId * @param int $lastCustomerId * @param string $referer @@ -214,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); @@ -257,6 +251,8 @@ public function testGetRedirect( } /** + * Redirect data provider + * * @return array */ public function getRedirectDataProvider() @@ -305,7 +301,12 @@ public function getRedirectDataProvider() ]; } - public function testBeforeRequestParams() + /** + * Verify before request params + * + * @return void + */ + public function testBeforeRequestParams(): void { $requestParams = [ 'param1' => 'value1', @@ -315,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); @@ -327,7 +331,6 @@ public function testBeforeRequestParams() $this->customerSession->expects($this->once()) ->method('getBeforeAction') ->willReturn($action); - $this->resultForward->expects($this->once()) ->method('setParams') ->with($requestParams) @@ -344,7 +347,6 @@ public function testBeforeRequestParams() ->method('forward') ->with($action) ->willReturnSelf(); - $this->resultFactory->expects($this->once()) ->method('create') ->with(ResultFactory::TYPE_FORWARD) @@ -353,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/etc/di.xml b/app/code/Magento/Customer/etc/di.xml old mode 100755 new mode 100644 From fb0f0acc084fff95162ea806ca746c58e7c630a7 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 12 Feb 2020 15:15:20 +0200 Subject: [PATCH 599/666] Unit test for \Magento\MediaGallery\Plugin\Wysiwyg\Images\Storage --- .../Plugin/Wysiwyg/Images/StorageTest.php | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 app/code/Magento/MediaGallery/Test/Unit/Plugin/Wysiwyg/Images/StorageTest.php 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); + } +} From 2c56525bd9ddb9abf7e2660f4eeb9ca4bafa407d Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Wed, 12 Feb 2020 16:36:39 +0200 Subject: [PATCH 600/666] MC-29766: [Upport 2.4.0] [FT] Test StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest randomly failed on Jenkins --- ...oreInformationConfigurationActionGroup.xml | 36 ++++++ .../AdminGeneralStoreInfomationConfigData.xml | 7 ++ ...tStorefrontOrderIsNotPlacedActionGroup.xml | 14 +++ ...koutClickNextOnShippingStepActionGroup.xml | 14 +++ .../Mftf/Section/CheckoutHeaderSection.xml | 1 + ...ippingMethodInReviewAndPaymentStepTest.xml | 105 +++++++++--------- .../Customer/Test/Mftf/Data/AddressData.xml | 1 + ...StorefrontApplyDiscountCodeActionGroup.xml | 3 +- .../Test/Mftf/Section/DiscountSection.xml | 2 +- ...ShippingOriginConfigurationActionGroup.xml | 19 ++++ ...ShippingOriginConfigurationActionGroup.xml | 23 ++++ .../Data/AdminShippingSettingsConfigData.xml | 14 +++ .../Mftf/Metadata/shipping_origin-meta.xml | 32 ++++++ 13 files changed, 216 insertions(+), 55 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminSetStoreInformationConfigurationActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml create mode 100644 app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminResetShippingOriginConfigurationActionGroup.xml create mode 100644 app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml create mode 100644 app/code/Magento/Shipping/Test/Mftf/Metadata/shipping_origin-meta.xml 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 @@ +<?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="AdminSetStoreInformationConfigurationActionGroup"> + <annotations> + <description>Set Store Information configurations</description> + </annotations> + <arguments> + <argument name="storeName" type="string" defaultValue="{{AdminGeneralSetStoreNameConfigData.value}}"/> + <argument name="storeHoursOfOperation" type="string" defaultValue="{{AdminGeneralSetStoreHoursConfigData.value}}"/> + <argument name="vatNumber" type="string" defaultValue="{{AdminGeneralSetVatNumberConfigData.value}}"/> + <argument name="telephone" type="string" defaultValue="{{US_Address_TX.telephone}}"/> + <argument name="country" type="string" defaultValue="{{US_Address_TX.country_id}}"/> + <argument name="state" type="string" defaultValue="{{US_Address_TX.state}}"/> + <argument name="city" type="string" defaultValue="{{US_Address_TX.city}}"/> + <argument name="postcode" type="string" defaultValue="{{US_Address_TX.postcode}}"/> + <argument name="street" type="string" defaultValue="{{US_Address_TX.street[0]}}"/> + </arguments> + <magentoCLI command="config:set {{AdminGeneralSetStoreNameConfigData.path}} '{{storeName}}'" stepKey="setStoreInformationName"/> + <magentoCLI command="config:set {{AdminGeneralSetStorePhoneConfigData.path}} '{{telephone}}'" stepKey="setStoreInformationPhone"/> + <magentoCLI command="config:set {{AdminGeneralSetStoreHoursConfigData.path}} '{{storeHoursOfOperation}}'" stepKey="setStoreHoursInformation"/> + <magentoCLI command="config:set {{AdminGeneralSetCountryConfigData.path}} '{{country}}'" stepKey="setStoreInformationCountry"/> + <magentoCLI command="config:set {{AdminGeneralSetStateConfigData.path}} '{{state}}'" stepKey="setStoreInformationState"/> + <magentoCLI command="config:set {{AdminGeneralSetCityConfigData.path}} '{{city}}'" stepKey="setStoreInformationCity"/> + <magentoCLI command="config:set {{AdminGeneralSetPostcodeConfigData.path}} '{{postcode}}'" stepKey="setStoreInformationPostcode"/> + <magentoCLI command="config:set {{AdminGeneralSetStreetAddressConfigData.path}} '{{street}}'" stepKey="setStoreInformationStreetAddress"/> + <magentoCLI command="config:set {{AdminGeneralSetVatNumberConfigData.path}} '{{vatNumber}}'" stepKey="setStoreInformationVatNumber"/> + </actionGroup> +</actionGroups> 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 @@ <entity name="AdminGeneralSetStreetAddress2ConfigData"> <data key="path">general/store_information/street_line2</data> </entity> + <entity name="AdminGeneralSetStateConfigData"> + <data key="path">general/store_information/region_id</data> + </entity> + <entity name="AdminGeneralSetStoreHoursConfigData"> + <data key="path">general/store_information/hours</data> + <data key="value">8AM-8PM</data> + </entity> </entities> 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..a0197c244259f --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml @@ -0,0 +1,14 @@ +<?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"> + <remove keyForRemoval="assertErrorMessage"/> + <seeElementInDOM selector="{{CheckoutHeaderSection.errorMessageContainsText(error)}}" stepKey="assertErrorMessageInDOM"/> + </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..708fd605dc1ea --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml @@ -0,0 +1,14 @@ +<?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"> + <scrollTo selector="{{CheckoutShippingSection.next}}" before="clickNext" stepKey="scrollToNextButton"/> + </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/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest.xml index f11d25a30f073..cb3b8a1934e4c 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="logout" 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/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/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/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..9e29a6dc4bcce --- /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"/> + </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> From 5cc2dc77f59d941b524e5879318ab0b7e509cebe Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 12 Feb 2020 16:51:31 +0200 Subject: [PATCH 601/666] add case when active element is input --- .../js/grid/columns/image-preview.test.js | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) 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 38c7003f08838..c762826734be2 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(); @@ -48,25 +64,9 @@ define([ }); describe('handleKeyDown method', function () { + it('veify record changed on key down', function () { - var recordMock = { - _rowIndex: 2 - }, - secondRecordMock = { - _rowIndex: 1, - rowNumber: 1 - }, - elementMock = { - keyCode: 37 - }, - masonryMock = { - shows: jasmine.createSpy().and.returnValue([]), - rows: jasmine.createSpy().and.returnValue({ - 1: secondRecordMock - }) - - }, - imageMock = document.createElement('img'), + var imageMock = document.createElement('img'), originMock = $.fn.get; spyOn($.fn, 'get').and.returnValue(imageMock); @@ -76,9 +76,22 @@ define([ imagePreview.masonry = jasmine.createSpy().and.returnValue(masonryMock); imagePreview.handleKeyDown(elementMock); expect(imagePreview.displayedRecord()._rowIndex).toBe(secondRecordMock._rowIndex); + $.fn.get = originMock; }); + it('veify 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(); + }); }); }); }); From 88a5e35d3642cdfe03097f594c42d691548cca05 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Wed, 12 Feb 2020 16:52:27 +0200 Subject: [PATCH 602/666] Unit Tests for observers from Magento_Reports --- .../SendfriendProductObserverTest.php | 93 +++++++++++++++++++ .../WishlistAddProductObserverTest.php | 93 +++++++++++++++++++ .../Observer/WishlistShareObserverTest.php | 93 +++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 app/code/Magento/Reports/Test/Unit/Observer/SendfriendProductObserverTest.php create mode 100644 app/code/Magento/Reports/Test/Unit/Observer/WishlistAddProductObserverTest.php create mode 100644 app/code/Magento/Reports/Test/Unit/Observer/WishlistShareObserverTest.php 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); + } +} From 7a88ffc63d9578865e19b9946a7bf368d6a1dda6 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 12 Feb 2020 16:53:43 +0200 Subject: [PATCH 603/666] fix typo --- .../Magento/Ui/base/js/grid/columns/image-preview.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c762826734be2..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 @@ -65,7 +65,7 @@ define([ describe('handleKeyDown method', function () { - it('veify record changed on key down', function () { + it('verify record changed on key down', function () { var imageMock = document.createElement('img'), originMock = $.fn.get; @@ -80,7 +80,7 @@ define([ $.fn.get = originMock; }); - it('veify record not changed on key down when active element input', function () { + it('verify record not changed on key down when active element input', function () { var input = $('<input id=\'input-fixture\'/>'); $(document.body).append(input); From 315a80f5e55de71e857623879ade336571bc4ccb Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 12 Feb 2020 17:42:26 +0200 Subject: [PATCH 604/666] MC-30521: [2.4][FT] Test StorefrontShareWishlistEntityTest fails on Jenkins --- .../StorefrontShareWishlistEntityTest.xml | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml index bb566ef2d03a4..4ccb13224d7a0 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"/> <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> From 05256c8f9f61ffbd7a25b78be9decefe13c3f29f Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 12 Feb 2020 18:41:05 +0200 Subject: [PATCH 605/666] magento/magento2#: GraphQL. setPaymentMethodOnCart mutation. Extend list of required parameters for testSetPaymentMethodWithoutRequiredParameters. --- .../GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php | 4 ++++ .../GraphQl/Quote/Guest/SetPaymentMethodOnCartTest.php | 4 ++++ 2 files changed, 8 insertions(+) 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.' From fd42cdd722016ead58f5f830764e0f2135fd6206 Mon Sep 17 00:00:00 2001 From: Slava Mankivski <mankivsk@adobe.com> Date: Wed, 12 Feb 2020 21:40:37 -0600 Subject: [PATCH 606/666] Updated composer.lock --- composer.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index 9620c73c90ba4..347a50bdf68e0 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": "fed60ae2b1869a71f2068e4f55a8695f", + "content-hash": "3b292997ff7767b89b6e08b0c550db7d", "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", @@ -1850,11 +1850,6 @@ "MIT" ], "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1862,6 +1857,11 @@ { "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).", From f6e12effa0cc84e22ef54608706230761383ebdf Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Thu, 13 Feb 2020 09:26:53 +0200 Subject: [PATCH 607/666] MC-29766: [Upport 2.4.0] [FT] Test StorefrontNotApplicableShippingMethodInReviewAndPaymentStepTest randomly failed on Jenkins --- .../AssertStorefrontOrderIsNotPlacedActionGroup.xml | 3 +++ .../StorefrontCheckoutClickNextOnShippingStepActionGroup.xml | 4 ++++ .../AdminSetShippingOriginConfigurationActionGroup.xml | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml index a0197c244259f..18fc6fac18085 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontOrderIsNotPlacedActionGroup.xml @@ -8,6 +8,9 @@ <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> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml index 708fd605dc1ea..1e86becdc0888 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutClickNextOnShippingStepActionGroup.xml @@ -9,6 +9,10 @@ <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/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml index 9e29a6dc4bcce..ad92cade0b941 100644 --- a/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml +++ b/app/code/Magento/Shipping/Test/Mftf/ActionGroup/AdminSetShippingOriginConfigurationActionGroup.xml @@ -13,7 +13,7 @@ <description>Set Shipping Origin configurations</description> </annotations> <arguments> - <argument name="address"/> + <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"/> From 4cf2ec8b0f4e5e4141e4804ea74a937b5552964e Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 13 Feb 2020 10:19:49 +0200 Subject: [PATCH 608/666] MC-24260: Automate (convert) integration test MC-26219 --- .../Magento/CatalogImportExport/Model/Import/ProductTest.php | 1 + .../_files/import_product_with_empty_attribute_value.csv | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) 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 6f990ca06f0eb..0d868af76d8a5 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -3049,5 +3049,6 @@ public function testEmptyAttributeValueShouldBeIgnoredAfterUpdateProductByImport $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')); } } 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 index 11c8e294bb71a..8ebaf0b64319e 100644 --- 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 @@ -1,2 +1,2 @@ -sku,name,product_type,attribute_set_code,price,qty,additional_attributes -simple,Simple Product,simple,Default,10,100,varchar_attribute= +sku,name,short_description,product_type,attribute_set_code,price,qty,additional_attributes +simple,Simple Product,,simple,Default,10,100,varchar_attribute= From bab4fb677ea110d614d434937264fc107ac75c1d Mon Sep 17 00:00:00 2001 From: "Vincent.Le" <vinh.le2@niteco.se> Date: Thu, 13 Feb 2020 17:46:23 +0700 Subject: [PATCH 609/666] Issue/26843: Fix es_US Spanish (United States ) Locale is not supported in Magento 2.3.4 #26843 --- lib/internal/Magento/Framework/Locale/Config.php | 1 + 1 file changed, 1 insertion(+) 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)*/ ]; /** From 13200a8c9144a4f7447ee9369ce69d2ae43bdabe Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Thu, 13 Feb 2020 17:51:49 +0530 Subject: [PATCH 610/666] Code Refactored with data provider --- .../Analytics/ReportXml/QueryFactory.php | 69 ++++++------ .../Test/Unit/ReportXml/QueryFactoryTest.php | 104 ++++++++++-------- 2 files changed, 93 insertions(+), 80 deletions(-) diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index 2293a242c453a..cfd26554b35a2 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -1,14 +1,15 @@ <?php + /** * 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\ObjectManagerInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\DB\Select; @@ -50,20 +51,20 @@ class QueryFactory private $selectHydrator; /** - * @var Json|null + * @var Json */ private $jsonSerializer; /** * QueryFactory constructor. * - * @param CacheInterface $queryCache - * @param SelectHydrator $selectHydrator + * @param CacheInterface $queryCache + * @param SelectHydrator $selectHydrator * @param ObjectManagerInterface $objectManager - * @param SelectBuilderFactory $selectBuilderFactory - * @param Config $config - * @param array $assemblers - * @param Json|null $jsonSerializer + * @param SelectBuilderFactory $selectBuilderFactory + * @param Config $config + * @param array $assemblers + * @param Json $jsonSerializer */ public function __construct( CacheInterface $queryCache, @@ -72,7 +73,7 @@ public function __construct( SelectBuilderFactory $selectBuilderFactory, Config $config, array $assemblers, - Json $jsonSerializer = null + Json $jsonSerializer ) { $this->config = $config; $this->selectBuilderFactory = $selectBuilderFactory; @@ -80,7 +81,7 @@ public function __construct( $this->queryCache = $queryCache; $this->objectManager = $objectManager; $this->selectHydrator = $selectHydrator; - $this->jsonSerializer = $jsonSerializer ?: ObjectManager::getInstance()->get(Json::class); + $this->jsonSerializer = $jsonSerializer; } /** @@ -120,31 +121,10 @@ private function constructQuery($queryName) ); } - /** - * Create query class using objectmanger - * - * @param Select $select - * @param string $connection - * @param array $queryConfig - * @return Query - */ - private function createQueryObject($select, $connection, $queryConfig) - { - return $this->objectManager->create( - Query::class, - [ - 'select' => $select, - 'selectHydrator' => $this->selectHydrator, - 'connectionName' => $connection, - 'config' => $queryConfig - ] - ); - } - /** * Creates query by name * - * @param string $queryName + * @param string $queryName * @return Query */ public function create($queryName) @@ -165,4 +145,29 @@ public function create($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 + ): Query + { + return $this->objectManager->create( + Query::class, + [ + 'select' => $select, + 'selectHydrator' => $this->selectHydrator, + 'connectionName' => $connection, + 'config' => $queryConfig + ] + ); + } } diff --git a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php index 1a11b293400db..032ef1e107825 100644 --- a/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php +++ b/app/code/Magento/Analytics/Test/Unit/ReportXml/QueryFactoryTest.php @@ -142,59 +142,21 @@ protected function setUp(): void ); } - /** - * Get Query Data Mock - * - * @return array - */ - private function getQueryDataMock(): array - { - return [ - 'connectionName' => self::STUB_CONNECTION, - 'config' => [ - 'name' => self::STUB_QUERY_NAME, - 'connection' => self::STUB_CONNECTION - ], - '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( - Query::class, - [ - 'select' => $this->selectMock, - 'selectHydrator' => $this->selectHydratorMock, - 'connectionName' => $queryDataMock['connectionName'], - 'config' => $queryDataMock['config'] - ] - ) - ->willReturn($this->queryMock); - } - /** * Test create() if query cached * * @return void + * @dataProvider queryDataProvider */ - public function testCreateIfQueryCached(): void + public function testCreateIfQueryCached(array $queryDataMock, string $jsonEncodeData): void { - $queryName = self::STUB_QUERY_NAME; - $queryDataMock = $this->getQueryDataMock(); + $queryConfigMock = $queryDataMock['config']; + $queryName = $queryConfigMock['name']; $this->queryCacheMock->expects($this->any()) ->method('load') ->with($queryName) - ->willReturn(json_encode($queryDataMock)); + ->willReturn($jsonEncodeData); $this->jsonSerializerMock->expects($this->once()) ->method('unserialize') @@ -220,12 +182,12 @@ public function testCreateIfQueryCached(): void * Test create() if query not cached * * @return void + * @dataProvider queryDataProvider */ - public function testCreateIfQueryNotCached(): void + public function testCreateIfQueryNotCached(array $queryDataMock, string $jsonEncodeData): void { - $queryName = self::STUB_QUERY_NAME; - $queryDataMock = $this->getQueryDataMock(); $queryConfigMock = $queryDataMock['config']; + $queryName = $queryConfigMock['name']; $selectBuilderMock = $this->getMockBuilder(SelectBuilder::class) ->disableOriginalConstructor() @@ -263,15 +225,61 @@ public function testCreateIfQueryNotCached(): void $this->jsonSerializerMock->expects($this->once()) ->method('serialize') - ->willReturn($this->queryMock); + ->willReturn($jsonEncodeData); $this->queryCacheMock->expects($this->once()) ->method('save') - ->with($this->queryMock, $queryName); + ->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( + Query::class, + [ + 'select' => $this->selectMock, + 'selectHydrator' => $this->selectHydratorMock, + 'connectionName' => $queryDataMock['connectionName'], + 'config' => $queryDataMock['config'] + ] + ) + ->willReturn($this->queryMock); + } } From ecc4ef5c9f60c416ce45fc1ea10071fd30336fe8 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Thu, 13 Feb 2020 14:59:09 +0200 Subject: [PATCH 611/666] add mftf test --- .../Catalog/Test/Mftf/Data/TierPriceData.xml | 10 ++- ...uctWithSpecialAndTierDiscountPriceTest.xml | 68 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml 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/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml new file mode 100644 index 0000000000000..f1dfdad601488 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml @@ -0,0 +1,68 @@ +<?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> + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create product --> + <createData entity="ApiSimpleProduct" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + <field key="price">100.00</field> + </createData> + + <!-- Add tier price to product --> + <createData entity="tierProductPriceDiscount" stepKey="addTierPrice"> + <requiredEntity createDataKey="createProduct"/> + </createData> + + <!-- Add special price to product --> + <createData entity="specialProductPrice2" stepKey="addSpecialToSimpleProduct"> + <requiredEntity createDataKey="createProduct"/> + <field key="price">65.00</field> + </createData> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + <!-- Open product page --> + <amOnPage url="{{StorefrontProductPage.url($createProduct.sku$)}}" stepKey="openProductPage"/> + <waitForPageLoad stepKey="waitForProductPageLoad"/> + + <!-- Assert product name on product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="productNameText"/> + <assertEquals stepKey="assertProductNameOnProductPage"> + <expectedResult type="string">$createProduct.name$</expectedResult> + <actualResult type="variable">productNameText</actualResult> + </assertEquals> + + <!-- Assert product tier price on product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> + <assertEquals stepKey="assertTierPriceTextOnProductPage"> + <expectedResult type="string">Buy {{tierProductPriceDiscount.quantity}} for $64.00 each and save 2%</expectedResult> + <actualResult type="variable">tierPriceText</actualResult> + </assertEquals> + + <!-- Assert final product price on product page --> + <grabTextFrom selector="{{StorefrontProductInfoMainSection.price}}" stepKey="productPriceText"/> + <assertEquals stepKey="assertProductPriceOnProductPage"> + <expectedResult type="string">$65.00</expectedResult> + <actualResult type="variable">productPriceText</actualResult> + </assertEquals> + </test> +</tests> From e147b760a6c5966621c7a93bcbc5b74a878f7976 Mon Sep 17 00:00:00 2001 From: Sathish <srsathish92@gmail.com> Date: Thu, 13 Feb 2020 19:22:06 +0530 Subject: [PATCH 612/666] Static test fixed --- app/code/Magento/Analytics/ReportXml/QueryFactory.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index cfd26554b35a2..a54990a1a035d 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -87,7 +87,7 @@ public function __construct( /** * Returns query connection name according to configuration * - * @param string $queryConfig + * @param string $queryConfig * @return string */ private function getQueryConnectionName($queryConfig) @@ -102,7 +102,7 @@ private function getQueryConnectionName($queryConfig) /** * Create query according to configuration settings * - * @param string $queryName + * @param string $queryName * @return Query */ private function constructQuery($queryName) @@ -158,8 +158,7 @@ private function createQueryObject( Select $select, string $connection, array $queryConfig - ): Query - { + ) { return $this->objectManager->create( Query::class, [ From 464fee964c4f02e35287009f3f7a8d46eeaa26d1 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 13 Feb 2020 16:48:07 +0200 Subject: [PATCH 613/666] MC-31303: [2.4] Add To Cart enabled button element added --- .../Test/Mftf/Section/StorefrontProductInfoMainSection.xml | 2 ++ 1 file changed, 2 insertions(+) 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> From 66d2cbcfb0f2f8f1d83c515cdc869a7fbfafdd85 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 12 Feb 2020 11:39:10 +0200 Subject: [PATCH 614/666] Cover change tests, fix static --- .../Framework/Filesystem/Driver/FileTest.php | 34 ++++++- .../Framework/Filesystem/Io/FileTest.php | 92 +++++++++++++++++++ .../Framework/Filesystem/Driver/File.php | 8 +- .../Framework/Filesystem/Driver/Http.php | 11 ++- .../Magento/Framework/Filesystem/Io/File.php | 31 +++++-- .../Filesystem/Test/Unit/Driver/HttpTest.php | 88 +++++++++++++++--- 6 files changed, 233 insertions(+), 31 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/Filesystem/Io/FileTest.php 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/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 3251f5af1bad3..4d5ba7a1918ce 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -13,9 +13,8 @@ use Magento\Framework\Filesystem\Glob; /** - * Class File + * Driver file class * - * @package Magento\Framework\Filesystem\Driver * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class File implements DriverInterface @@ -593,12 +592,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()]) ); } + return $result; } @@ -976,7 +978,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 9f76bb33335d3..0191d5d8a3040 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 + * Http driver file class. */ class Http extends File { @@ -196,8 +196,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/Io/File.php b/lib/internal/Magento/Framework/Filesystem/Io/File.php index 97b121beb42c2..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.') + ); } } @@ -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; From 5f7e34c1e91cf0ddc45300ec800f782162e17ff9 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Thu, 13 Feb 2020 18:55:48 +0200 Subject: [PATCH 615/666] MC-31262: Storefront: Reset/Forgot customer password --- .../testsuite/Magento/Customer/Controller/CreatePasswordTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php index 9ad25ae5ddd5f..bbaf55494294e 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/CreatePasswordTest.php @@ -74,7 +74,6 @@ protected function tearDown() parent::tearDown(); } - /** * @magentoDataFixture Magento/Customer/_files/customer_with_website.php * From 0a912c8fae1772876ae49a7cc62bc4a9ac0b445c Mon Sep 17 00:00:00 2001 From: tufa <tufa.hu@gmail.com> Date: Thu, 13 Feb 2020 18:05:35 +0100 Subject: [PATCH 616/666] toHtml method should be return with string --- .../Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php index 447ba16d72710..0ac4642eff8a2 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php @@ -23,6 +23,7 @@ public function toHtml() if (!$this->isMsrpPriceApplicable() && $this->isTierPriceApplicable()) { return parent::toHtml(); } + return ''; } /** From 205ee0facfc285eb3106f75c0cb40898526c3239 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Thu, 13 Feb 2020 13:24:08 -0600 Subject: [PATCH 617/666] MC-31499: [2.4] Re: Magento 2.3.4 | serious issues with local storage if custom sections.xml invalidations are active --- .../CustomerData/SectionConfigConverter.php | 17 ++++-- .../SectionConfigConverterTest.php | 54 +++++++++++++++++-- .../Unit/CustomerData/_files/sections.xml | 50 ++++++++++++++++- .../Unit/CustomerData/_files/sections2.xml | 40 ++++++++++++++ .../Customer/etc/frontend/sections.xml | 16 ++++-- .../Directory/etc/frontend/sections.xml | 4 +- .../Magento/Store/etc/frontend/sections.xml | 8 ++- 7 files changed, 175 insertions(+), 14 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Unit/CustomerData/_files/sections2.xml 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/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/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/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/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> From da405a0326141ab07db809937d04aca0c8706d25 Mon Sep 17 00:00:00 2001 From: Vladimir Fishchenko <hws47a@gmail.com> Date: Thu, 13 Feb 2020 21:19:15 +0000 Subject: [PATCH 618/666] Update MockObject class in Wishlist module --- .../Widget/Grid/Column/Filter/TextTest.php | 2 +- .../Renderer/Actions/MoveToWishlistTest.php | 4 +- .../Test/Unit/Block/Customer/SidebarTest.php | 6 +- .../Customer/Wishlist/Item/OptionsTest.php | 8 +-- .../Test/Unit/Block/Item/ConfigureTest.php | 6 +- .../Test/Unit/Block/Rss/EmailLinkTest.php | 6 +- .../Wishlist/Test/Unit/Block/Rss/LinkTest.php | 8 +-- .../Unit/Controller/Index/AllcartTest.php | 20 +++--- .../Test/Unit/Controller/Index/CartTest.php | 38 ++++++------ .../Unit/Controller/Index/FromcartTest.php | 24 +++---- .../Test/Unit/Controller/Index/IndexTest.php | 16 ++--- .../Test/Unit/Controller/Index/PluginTest.php | 12 ++-- .../Test/Unit/Controller/Index/RemoveTest.php | 20 +++--- .../Test/Unit/Controller/Index/SendTest.php | 34 +++++----- .../Test/Unit/Controller/Index/ShareTest.php | 6 +- .../Index/UpdateItemOptionsTest.php | 24 +++---- .../Test/Unit/Controller/Index/UpdateTest.php | 2 +- .../Unit/Controller/Shared/AllcartTest.php | 14 ++--- .../Test/Unit/Controller/Shared/CartTest.php | 34 +++++----- .../Test/Unit/CustomerData/WishlistTest.php | 26 ++++---- .../Product/Collector/ButtonTest.php | 6 +- .../Wishlist/Test/Unit/Helper/DataTest.php | 28 ++++----- .../Wishlist/Test/Unit/Helper/RssTest.php | 16 ++--- .../Wishlist/Test/Unit/Model/ConfigTest.php | 6 +- .../Test/Unit/Model/ItemCarrierTest.php | 62 +++++++++---------- .../Wishlist/Test/Unit/Model/ItemTest.php | 20 +++--- .../Model/LocaleQuantityProcessorTest.php | 4 +- .../Product/AttributeValueProviderTest.php | 10 +-- .../ResourceModel/Item/CollectionTest.php | 2 +- .../Test/Unit/Model/Rss/WishlistTest.php | 2 +- .../Wishlist/Test/Unit/Model/WishlistTest.php | 38 ++++++------ .../Test/Unit/Observer/AddToCartTest.php | 12 ++-- .../Unit/Observer/CartUpdateBeforeTest.php | 12 ++-- .../Test/Unit/Observer/CustomerLoginTest.php | 2 +- .../Test/Unit/Observer/CustomerLogoutTest.php | 2 +- .../Ui/DataProvider/WishlistSettingsTest.php | 4 +- .../ConfigurableProductTest.php | 8 +-- .../ConfiguredPrice/DownloadableTest.php | 8 +-- .../Pricing/Render/ConfiguredPriceBoxTest.php | 10 +-- 39 files changed, 281 insertions(+), 281 deletions(-) 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..f79cbb9df5445 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php @@ -13,7 +13,7 @@ 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 @@ -21,22 +21,22 @@ 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..1b61202c42b30 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; 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; From 7950514ceb8db77cf5c31784dccdfd54c8468e7f Mon Sep 17 00:00:00 2001 From: Vladimir Fishchenko <hws47a@gmail.com> Date: Thu, 13 Feb 2020 21:27:25 +0000 Subject: [PATCH 619/666] Update MockObject class in Widget module --- .../Widget/Catalog/Category/ChooserTest.php | 20 +++++++++---------- .../Edit/Chooser/AbstractContainerTest.php | 18 ++++++++--------- .../Instance/Edit/Tab/PropertiesTest.php | 4 ++-- .../Widget/Instance/CategoriesTest.php | 14 ++++++------- .../Adminhtml/Widget/LoadOptionsTest.php | 20 +++++++++---------- .../Test/Unit/Helper/ConditionsTest.php | 4 ++-- .../Unit/Model/Config/FileResolverTest.php | 6 +++--- .../Test/Unit/Model/NamespaceResolverTest.php | 2 +- .../ResourceModel/Layout/AbstractTestCase.php | 4 ++-- .../Layout/Link/CollectionTest.php | 4 ++-- .../Layout/Update/CollectionTest.php | 2 +- .../Widget/Instance/Options/ThemesTest.php | 4 ++-- .../Unit/Model/Template/FilterEmulateTest.php | 2 +- .../Test/Unit/Model/Template/FilterTest.php | 14 ++++++------- .../Test/Unit/Model/Widget/InstanceTest.php | 12 +++++------ .../Widget/Test/Unit/Model/WidgetTest.php | 4 ++-- 16 files changed, 67 insertions(+), 67 deletions(-) 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..6c16489924f54 100644 --- a/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php +++ b/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php @@ -20,12 +20,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; From ac143c6d84dc7c7ffbf11c39d17940e946764f95 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 13 Feb 2020 15:55:13 -0600 Subject: [PATCH 620/666] MQE-2003: Bump MFTF version in Magento MFTF2.6.2 --- composer.json | 2 +- composer.lock | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 8d38f1e0a151e..9c42a05a457c5 100644 --- a/composer.json +++ b/composer.json @@ -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.6.1", + "magento/magento2-functional-testing-framework": "2.6.2", "pdepend/pdepend": "2.5.2", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "@stable", diff --git a/composer.lock b/composer.lock index 347a50bdf68e0..6ac7f36cd2e32 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": "3b292997ff7767b89b6e08b0c550db7d", + "content-hash": "f06887dfc3e06489a251fbb5c18d30ca", "packages": [ { "name": "braintree/braintree_php", @@ -1850,6 +1850,11 @@ "MIT" ], "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -1857,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).", @@ -7381,16 +7381,16 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.6.1", + "version": "2.6.2", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db" + "reference": "8b332582751a830b3a6eafe1b09ac3b403e9a20e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/b00f5e195e1ed7f6335bce3052be9a0291f4d0db", - "reference": "b00f5e195e1ed7f6335bce3052be9a0291f4d0db", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/8b332582751a830b3a6eafe1b09ac3b403e9a20e", + "reference": "8b332582751a830b3a6eafe1b09ac3b403e9a20e", "shasum": "" }, "require": { @@ -7462,7 +7462,7 @@ "magento", "testing" ], - "time": "2020-02-11T22:23:54+00:00" + "time": "2020-02-13T21:29:32+00:00" }, { "name": "mikey179/vfsstream", From fcc606be44acb8c215fc8731383cbb6fdafaa132 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 14 Feb 2020 12:17:08 +0200 Subject: [PATCH 621/666] MC-31424: Create test for issue "<" and ">" symbols are changed to "<" and ">" in the frontend catalog search line --- .../CatalogSearch/Block/ResultTest.php | 90 +++++++++++++++++-- 1 file changed, 82 insertions(+), 8 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index 9c02623085cab..e1638d87c924f 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 elasticsearch7 + * @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;'], + ]; + } } From 4801a94b205658aec7420cc94bc3572e922d6231 Mon Sep 17 00:00:00 2001 From: DianaRusin <rusind95@gmail.com> Date: Fri, 14 Feb 2020 12:31:22 +0200 Subject: [PATCH 622/666] MC-31424: Create test for issue "<" and ">" symbols are changed to "<" and ">" in the frontend catalog search line --- .../testsuite/Magento/CatalogSearch/Block/ResultTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index e1638d87c924f..e36e3dee65954 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php @@ -48,7 +48,7 @@ public function testSetListOrders() /** * Verify search value escaping process * - * @magentoConfigFixture default/catalog/search/engine elasticsearch7 + * @magentoConfigFixture default/catalog/search/engine elasticsearch6 * @dataProvider toEscapeSearchTextDataProvider * @magentoAppArea frontend * @param string $searchValue From 5e6fe4c7dac91dc2ed1f1fea5f1e83be2316bdb1 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 14 Feb 2020 12:56:46 +0200 Subject: [PATCH 623/666] MC-31443: [FT] [MFTF] [2.4] Fix flaky test AdminReorderWithCatalogPriceTest (MC-16695) --- ...orderWithCatalogPriceRuleDiscountTest.xml} | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) rename app/code/Magento/Sales/Test/Mftf/Test/{AdminReorderWithCatalogPriceTest.xml => AdminReorderWithCatalogPriceRuleDiscountTest.xml} (68%) 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..ccdf90cc648c5 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="logout" 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> From 24b3fba8e2506f74cbd10bd8b9ae187c6ff8b062 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 14 Feb 2020 14:21:23 +0200 Subject: [PATCH 624/666] fix mftf --- ...ProductDetailPageFinalPriceActionGroup.xml | 20 ++++++++++ ...efrontProductDetailPageNameActionGroup.xml | 20 ++++++++++ ...tProductDetailPageTierPriceActionGroup.xml | 22 +++++++++++ ...uctWithSpecialAndTierDiscountPriceTest.xml | 39 +++++++------------ 4 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageFinalPriceActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageNameActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductDetailPageTierPriceActionGroup.xml 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/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml index f1dfdad601488..a7042bdda41c1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml @@ -16,21 +16,17 @@ <group value="Catalog"/> </annotations> <before> - <!-- Create category --> <createData entity="_defaultCategory" stepKey="createCategory"/> - <!-- Create product --> <createData entity="ApiSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> <field key="price">100.00</field> </createData> - <!-- Add tier price to product --> <createData entity="tierProductPriceDiscount" stepKey="addTierPrice"> <requiredEntity createDataKey="createProduct"/> </createData> - <!-- Add special price to product --> <createData entity="specialProductPrice2" stepKey="addSpecialToSimpleProduct"> <requiredEntity createDataKey="createProduct"/> <field key="price">65.00</field> @@ -40,29 +36,24 @@ <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> </after> - <!-- Open product page --> - <amOnPage url="{{StorefrontProductPage.url($createProduct.sku$)}}" stepKey="openProductPage"/> + + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> + <argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/> + </actionGroup> <waitForPageLoad stepKey="waitForProductPageLoad"/> - <!-- Assert product name on product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productName}}" stepKey="productNameText"/> - <assertEquals stepKey="assertProductNameOnProductPage"> - <expectedResult type="string">$createProduct.name$</expectedResult> - <actualResult type="variable">productNameText</actualResult> - </assertEquals> + <actionGroup ref="AssertStorefrontProductDetailPageNameActionGroup" stepKey="assertProductNameText"> + <argument name="productName" value="$createProduct.name$"/> + </actionGroup> - <!-- Assert product tier price on product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.tierPriceText}}" stepKey="tierPriceText"/> - <assertEquals stepKey="assertTierPriceTextOnProductPage"> - <expectedResult type="string">Buy {{tierProductPriceDiscount.quantity}} for $64.00 each and save 2%</expectedResult> - <actualResult type="variable">tierPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertStorefrontProductDetailPageTierPriceActionGroup" stepKey="assertProductTierPriceText"> + <argument name="tierProductPriceDiscountQuantity" value="{{tierProductPriceDiscount.quantity}}"/> + <argument name="productPriceWithAppliedTierPriceDiscount" value="64.00"/> + <argument name="productSavedPricePercent" value="2"/> + </actionGroup> - <!-- Assert final product price on product page --> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.price}}" stepKey="productPriceText"/> - <assertEquals stepKey="assertProductPriceOnProductPage"> - <expectedResult type="string">$65.00</expectedResult> - <actualResult type="variable">productPriceText</actualResult> - </assertEquals> + <actionGroup ref="AssertStorefrontProductDetailPageFinalPriceActionGroup" stepKey="assertProductFinalPriceText"> + <argument name="finalProductPrice" value="65.00"/> + </actionGroup> </test> </tests> From 62f8c6c16fc116b1683ec14db311e2a9fdc0fa03 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 14 Feb 2020 14:38:00 +0200 Subject: [PATCH 625/666] added cron running --- ...toreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml index a7042bdda41c1..2071f32f20cef 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml @@ -31,6 +31,7 @@ <requiredEntity createDataKey="createProduct"/> <field key="price">65.00</field> </createData> + <magentoCLI command="cron:run --group=index" stepKey="runCronIndex"/> </before> <after> <deleteData createDataKey="createProduct" stepKey="deleteSimpleProduct"/> From aeb076de7d784cd801624746a8a65c1f11a4b77b Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 14 Feb 2020 15:05:30 +0200 Subject: [PATCH 626/666] Covering the New Relic plugins by Unit Tests --- .../Test/Unit/Plugin/HttpPluginTest.php | 98 +++++++++++++ .../Test/Unit/Plugin/StatePluginTest.php | 136 ++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 app/code/Magento/NewRelicReporting/Test/Unit/Plugin/HttpPluginTest.php create mode 100644 app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php 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..62d93a367f724 --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php @@ -0,0 +1,136 @@ +<?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 + ] + ]; + } +} From 303895ddc8f2e051c01510cee4e663fefe37be31 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 14 Feb 2020 15:30:45 +0200 Subject: [PATCH 627/666] MC-30521: [2.4][FT] Test StorefrontShareWishlistEntityTest fails on Jenkins --- .../Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml index 4ccb13224d7a0..329978462c107 100644 --- a/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml +++ b/app/code/Magento/Wishlist/Test/Mftf/Test/StorefrontShareWishlistEntityTest.xml @@ -15,7 +15,7 @@ <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"/> - <testCaseId value="MC-13976"/> + <testCaseId value="MC-27621"/> <group value="wishlist"/> <group value="mtf_migrated"/> </annotations> From 870b875af8c8097e9f889f03fb9d48055e902f94 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 14 Feb 2020 16:22:49 +0200 Subject: [PATCH 628/666] MC-31444: [FT] [MFTF] [2.4] Fix flaky test StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest (MC-41933) --- ...timateShippingAndTaxAddressActionGroup.xml | 31 ++++++ ...tFillEstimateShippingAndTaxActionGroup.xml | 28 ++++++ ...efrontCheckoutCartTaxAmountActionGroup.xml | 25 +++++ ...InShoppingCartForGuestVirtualQuoteTest.xml | 79 --------------- ...ontCheckoutCartTaxAmountFPTActionGroup.xml | 21 ++++ .../AdminProductAddFPTValueSection.xml | 8 +- ...ppingCartForCustomerPhysicalQuoteTest.xml} | 94 +++++++++--------- ...oppingCartForCustomerVirtualQuoteTest.xml} | 74 ++++++++------ ...ShoppingCartForGuestPhysicalQuoteTest.xml} | 88 +++++++++-------- ...InShoppingCartForGuestVirtualQuoteTest.xml | 96 +++++++++++++++++++ 10 files changed, 343 insertions(+), 201 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartEstimateShippingAndTaxAddressActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCartFillEstimateShippingAndTaxActionGroup.xml create mode 100644 app/code/Magento/Tax/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountActionGroup.xml delete mode 100644 app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml create mode 100644 app/code/Magento/Weee/Test/Mftf/ActionGroup/AssertStorefrontCheckoutCartTaxAmountFPTActionGroup.xml rename app/code/Magento/{Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml => Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml} (54%) rename app/code/Magento/{Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml => Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml} (52%) rename app/code/Magento/{Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml => Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml} (53%) create mode 100644 app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml 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/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/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/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/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 @@ +<?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="AssertStorefrontCheckoutCartTaxAmountFPTActionGroup" extends="AssertStorefrontCheckoutCartTaxAmountActionGroup"> + <annotations> + <description>EXTENDS: AssertStorefrontCheckoutCartTaxAmountActionGroup. Add check FPT tax summary in Summary section of shopping cart on storefront</description> + </annotations> + <arguments> + <argument name="FPTAmount" type="string" defaultValue="$10"/> + </arguments> + + <see selector="{{CheckoutCartSummarySection.amountFPT}}" userInput="{{FPTAmount}}" before="checkTaxAmount" stepKey="checkFPTAmount"/> + </actionGroup> +</actionGroups> 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 @@ <section name="AdminProductAddFPTValueSection"> <element name="addFPT" type="button" selector="[data-index='{{FPTAttributeCode}}'] [data-action='add_new_row']" parameterized="true"/> <element name="removeRowByIndex" type="button" selector="[data-index='{{FPTAttributeCode}}'] [data-action='remove_row']:nth-of-type({{rowIndex}})" parameterized="true"/> - <element name="selectCountryForFPT" type="select" selector="(//select[contains(@name, 'product[{{FPTAttributeCode}}]') and contains(@name, '[country]')])[last()]" parameterized="true"/> - <element name="selectStateForFPT" type="select" selector="(//select[contains(@name, 'product[{{FPTAttributeCode}}]') and contains(@name, '[state]')])[last()]" parameterized="true"/> - <element name="setTaxValueForFPT" type="text" selector="(//input[contains(@name, 'product[{{FPTAttributeCode}}]') and contains(@name, '[value]')])[last()]" parameterized="true"/> - <element name="setWebSiteForFPT" type="text" selector="(//select[contains(@name, 'product[{{FPTAttributeCode}}]') and contains(@name, '[website_id]')])[last()]" parameterized="true"/> + <element name="selectCountryForFPT" type="select" selector="div.admin__field-control[data-index='{{FPTAttributeCode}}'] table tbody tr.data-row:last-child select[name*='[country]']" parameterized="true"/> + <element name="selectStateForFPT" type="select" selector="div.admin__field-control[data-index='{{FPTAttributeCode}}'] table tbody tr.data-row:last-child select[name*='[state]']" parameterized="true"/> + <element name="setTaxValueForFPT" type="text" selector="div.admin__field-control[data-index='{{FPTAttributeCode}}'] table tbody tr.data-row:last-child input[name*='[value]']" parameterized="true"/> + <element name="setWebSiteForFPT" type="text" selector="div.admin__field-control[data-index='{{FPTAttributeCode}}'] table tbody tr.data-row:last-child select[name*='[website_id]']" parameterized="true"/> <element name="setWebSiteForFPTOption" type="text" selector="(//select[contains(@name, 'product[{{FPTAttributeCode}}]') and contains(@name, '[website_id]')])/option[contains(text(), '{{website}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml similarity index 54% rename from app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml rename to app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml index d81ea25de87a4..d0c3f517137d6 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 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontTaxInformationInShoppingCartForCustomerPhysicalQuoteTest"> + <test name="StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest"> <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 (physical quote)"/> <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-16526"/> <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 --> @@ -41,28 +44,27 @@ <!-- 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"/> @@ -71,55 +73,55 @@ <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="logout" 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..04c100e8413d5 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-16525"/> <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="logout" 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 53% rename from app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml rename to app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml index e8c2f1a66f0c3..08a234368754d 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-16538"/> <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 --> @@ -39,27 +42,25 @@ <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"/> @@ -67,49 +68,52 @@ <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="logout" 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..22f25e1a2a736 --- /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-11946"/> + <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="logout" 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> From af6f847299f85503ffe432ce40559508ad108271 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 14 Feb 2020 16:56:13 +0200 Subject: [PATCH 629/666] Static test fix --- .../Model/Product/Attribute/Source/Status.php | 4 ++-- .../Model/Product/Gallery/EntryResolver.php | 3 +++ .../ProductLink/Converter/ConverterPool.php | 3 +++ .../Catalog/Model/ProductLink/Link.php | 6 +++-- .../Block/Checkout/AttributeMerger.php | 2 ++ .../Config/Structure/Element/Section.php | 2 +- .../Customer/Ui/Component/Listing/Columns.php | 11 ++++++++- .../Magento/Deploy/Package/PackagePool.php | 24 +++++++++++++++++++ .../CollectionProcessor/FilterProcessor.php | 3 +++ .../Eav/Model/TypeLocator/SimpleType.php | 7 +++--- .../ImportExport/Model/Export/Config.php | 7 +++--- app/code/Magento/Paypal/Model/AbstractIpn.php | 6 +++++ app/code/Magento/Paypal/Model/Config.php | 1 + app/code/Magento/Paypal/Model/Info.php | 10 ++++++++ .../Paypal/Model/Payflow/AvsEmsCodeMapper.php | 3 +-- .../Paypal/Model/Payflow/CvvEmsCodeMapper.php | 3 +-- app/code/Magento/Paypal/Model/Payflowpro.php | 1 + .../Ui/Component/AbstractComponent.php | 7 +++++- .../Ui/Config/Reader/Definition/Data.php | 6 ----- .../Ui/DataProvider/AbstractDataProvider.php | 13 +++++++++- app/code/Magento/Ui/Model/Manager.php | 10 ++++---- app/code/Magento/User/Block/Role/Tab/Edit.php | 4 +++- .../Inspection/AbstractCommand.php | 6 +++++ 23 files changed, 113 insertions(+), 29 deletions(-) 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 92d3c9513ba40..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() { diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php b/app/code/Magento/Catalog/Model/Product/Gallery/EntryResolver.php index c706673ed222e..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 { /** diff --git a/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php b/app/code/Magento/Catalog/Model/ProductLink/Converter/ConverterPool.php index e90dc3c6b04b4..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 { /** diff --git a/app/code/Magento/Catalog/Model/ProductLink/Link.php b/app/code/Magento/Catalog/Model/ProductLink/Link.php index ad779eb0723b1..9286f9fb23629 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 @@ -169,7 +171,7 @@ public function setPosition($position) } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Catalog\Api\Data\ProductLinkExtensionInterface|null */ @@ -184,7 +186,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Catalog\Api\Data\ProductLinkExtensionInterface $extensionAttributes * @return $this diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 4543f1af61dc1..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,6 +382,7 @@ protected function getCustomer(): ?CustomerInterface /** * Retrieve field options from attribute configuration * + * @param mixed $attributeCode * @param array $attributeConfig * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) 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 e73bac986ad23..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 diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index c18e538f9365f..f47efd85838cf 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 { /** @@ -63,6 +66,8 @@ public function __construct( } /** + * Return default sort order + * * @return int */ protected function getDefaultSortOrder() @@ -94,7 +99,7 @@ protected function updateActionColumnSortOrder() } /** - * {@inheritdoc} + * @inheritdoc */ public function prepare() { @@ -113,6 +118,8 @@ public function prepare() } /** + * Add column to the component + * * @param array $attributeData * @param string $columnName * @return void @@ -129,6 +136,8 @@ public function addColumn(array $attributeData, $columnName) } /** + * Update column in component + * * @param array $attributeData * @param string $newAttributeCode * @return void diff --git a/app/code/Magento/Deploy/Package/PackagePool.php b/app/code/Magento/Deploy/Package/PackagePool.php index 17f5ca2425a89..9057f50fb3c91 100644 --- a/app/code/Magento/Deploy/Package/PackagePool.php +++ b/app/code/Magento/Deploy/Package/PackagePool.php @@ -60,6 +60,8 @@ public function __construct( } /** + * Return package + * * @param string $path * @return Package|null */ @@ -70,6 +72,8 @@ public function getPackage($path) } /** + * 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,6 +336,8 @@ private function isIncluded($entity, array $includedEntities, array $excludedEnt } /** + * Return option by name + * * @param string $name * @param array $options * @return mixed|null @@ -326,6 +348,8 @@ private function getOption($name, $options) } /** + * Ensure package exist + * * @param array $params * @return void */ 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 1625048ac92b8..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 { /** diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 81ceb26419633..225b912d24ed0 100644 --- a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php +++ b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php @@ -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) { @@ -63,7 +64,7 @@ public function getType($attributeCode, $entityType) } /** - * {@inheritDoc} + * @inheritDoc */ public function getAllServiceDataInterfaces() { diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php index 991bdb0984d36..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, diff --git a/app/code/Magento/Paypal/Model/AbstractIpn.php b/app/code/Magento/Paypal/Model/AbstractIpn.php index ec7e42a0f24b1..84903b92821b7 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 + */ class AbstractIpn { /** @@ -113,6 +116,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 +175,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 0cca6f219977e..6f6728ebfa47f 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -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 9e9423d7ac61e..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) { @@ -526,6 +533,7 @@ public static function explainReasonCode($code) * * @param string $code * @return bool; + * phpcs:disable Magento2.Functions.StaticFunction */ public static function isReversalDisputable($code) { @@ -617,6 +625,7 @@ protected function _getLabel($key) * * @param string $key * @return string + * phpcs:disable Magento2.Functions.StaticFunction */ public static function getCaseTypeLabel($key) { @@ -660,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; } diff --git a/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php b/app/code/Magento/Paypal/Model/Payflow/AvsEmsCodeMapper.php index 5c310816a975f..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 diff --git a/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php b/app/code/Magento/Paypal/Model/Payflow/CvvEmsCodeMapper.php index 856040a378a5a..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 diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 7557b6fc9474f..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) { diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index ba1abc62f522a..905cef2b8494d 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -14,6 +14,7 @@ use Magento\Framework\View\Element\UiComponent\ObserverInterface; use Magento\Framework\Data\ValueSourceInterface; +//phpcs:disable Magento2.Classes.AbstractApi /** * Abstract class AbstractComponent * @@ -173,6 +174,8 @@ public function addComponent($name, UiComponentInterface $component) } /** + * Return component + * * @param string $name * @return UiComponentInterface */ @@ -242,6 +245,7 @@ public function getJsConfig(UiComponentInterface $component) return $jsConfig; } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Component data setter * @@ -254,6 +258,7 @@ public function setData($key, $value = null) parent::setData($key, $value); } + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod /** * Component data getter * @@ -278,7 +283,7 @@ public function prepareDataSource(array $dataSource) } /** - * {@inheritdoc} + * @inheritdoc */ public function getDataSourceData() { diff --git a/app/code/Magento/Ui/Config/Reader/Definition/Data.php b/app/code/Magento/Ui/Config/Reader/Definition/Data.php index 32dd5a52edd91..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'; /** diff --git a/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php b/app/code/Magento/Ui/DataProvider/AbstractDataProvider.php index c403aedbd2638..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() @@ -131,6 +138,8 @@ public function getFieldSetMetaInfo($fieldSetName) } /** + * Return fields meta info + * * @param string $fieldSetName * @return array */ @@ -140,6 +149,8 @@ public function getFieldsMetaInfo($fieldSetName) } /** + * Return field meta info + * * @param string $fieldSetName * @param string $fieldName * @return array @@ -195,7 +206,7 @@ public function addField($field, $alias = null) } /** - * self::setOrder() alias + * Alias for self::setOrder() * * @param string $field * @param string $direction diff --git a/app/code/Magento/Ui/Model/Manager.php b/app/code/Magento/Ui/Model/Manager.php index 64ae7271fed8b..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) diff --git a/app/code/Magento/User/Block/Role/Tab/Edit.php b/app/code/Magento/User/Block/Role/Tab/Edit.php index f2663e29705d4..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 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; } From acf2f187084ed16352067ffa539f7e3b8c511e6b Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Fri, 14 Feb 2020 17:23:43 +0200 Subject: [PATCH 630/666] Fix static test attempt 2 :) --- app/code/Magento/Catalog/Model/ProductLink/Link.php | 2 ++ .../Customer/Ui/Component/Listing/AttributeRepository.php | 2 +- app/code/Magento/Customer/Ui/Component/Listing/Columns.php | 5 +++++ .../Eav/Model/Entity/Setup/PropertyMapperAbstract.php | 3 +++ app/code/Magento/Eav/Model/TypeLocator/SimpleType.php | 6 ++++-- .../Magento/Payment/Gateway/Data/Order/AddressAdapter.php | 2 +- .../Magento/Payment/Gateway/Data/Quote/AddressAdapter.php | 2 +- app/code/Magento/Paypal/Model/AbstractIpn.php | 7 ++++++- app/code/Magento/Ui/Component/AbstractComponent.php | 2 -- 9 files changed, 23 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductLink/Link.php b/app/code/Magento/Catalog/Model/ProductLink/Link.php index 9286f9fb23629..48945fbef9d52 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Link.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Link.php @@ -40,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']); diff --git a/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php b/app/code/Magento/Customer/Ui/Component/Listing/AttributeRepository.php index d577883673dcd..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 { diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php index f47efd85838cf..9bc164d7904d1 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Columns.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Columns.php @@ -32,6 +32,11 @@ class Columns extends \Magento\Ui\Component\Listing\Columns */ protected $inlineEditUpdater; + /** + * @var ColumnFactory + */ + private $columnFactory; + /** * @var array */ diff --git a/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php b/app/code/Magento/Eav/Model/Entity/Setup/PropertyMapperAbstract.php index a3b234181707c..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 { /** diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 225b912d24ed0..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; @@ -64,7 +64,9 @@ public function getType($attributeCode, $entityType) } /** - * @inheritDoc + * Get data Types from service type list + * + * @return void */ public function getAllServiceDataInterfaces() { diff --git a/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php index 9c0c2ea2afeae..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 { diff --git a/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php index a68dc1194c9f9..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 { diff --git a/app/code/Magento/Paypal/Model/AbstractIpn.php b/app/code/Magento/Paypal/Model/AbstractIpn.php index 84903b92821b7..f3f8909ecbd97 100644 --- a/app/code/Magento/Paypal/Model/AbstractIpn.php +++ b/app/code/Magento/Paypal/Model/AbstractIpn.php @@ -9,7 +9,7 @@ use Magento\Framework\Exception\RemoteServiceUnavailableException; /** - * Abstract Ipn class + * Abstract Ipn class for paypal */ class AbstractIpn { @@ -42,6 +42,11 @@ class AbstractIpn */ protected $_curlFactory; + /** + * @var \Psr\Log\LoggerInterface + */ + private $logger; + /** * @param \Magento\Paypal\Model\ConfigFactory $configFactory * @param \Psr\Log\LoggerInterface $logger diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index 905cef2b8494d..90c73f718426c 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -142,8 +142,6 @@ protected function prepareChildComponent(UiComponentInterface $component) /** * Produce and return block's html output - * - * @return string */ public function toHtml() { From 83ee9f6055c4caa5cd0ba67f1c5f5c8d53216385 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 14 Feb 2020 18:57:08 +0200 Subject: [PATCH 631/666] Removing the empty line --- .../NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php index 62d93a367f724..b2e75d0b435eb 100644 --- a/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php +++ b/app/code/Magento/NewRelicReporting/Test/Unit/Plugin/StatePluginTest.php @@ -71,7 +71,6 @@ public function setUp(): void 'logger' => $this->loggerMock, ] ); - } /** From a99fdb2f16a68f459d78e3f5a2a0f81beba007a6 Mon Sep 17 00:00:00 2001 From: Vladimir Fishchenko <hws47a@gmail.com> Date: Sat, 15 Feb 2020 01:18:35 +0000 Subject: [PATCH 632/666] Fix code style issues for Wishlist Unit Tests --- .../Test/Unit/Model/Product/AttributeValueProviderTest.php | 4 +++- .../Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) 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 f79cbb9df5445..62eb2605b3b64 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Model/Product/AttributeValueProviderTest.php @@ -16,7 +16,9 @@ use PHPUnit\Framework\MockObject\MockObject; /** - * AttributeValueProviderTest + * Class AttributeValueProviderTest + * + * PHPUnit test case for \Magento\Wishlist\Model\Product\AttributeValueProvider */ class AttributeValueProviderTest extends TestCase { diff --git a/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php b/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php index 1b61202c42b30..a9d05a7a99eec 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Observer/AddToCartTest.php @@ -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(); From f9000c0ae5826a220506bdcadd66ea908d229594 Mon Sep 17 00:00:00 2001 From: Vladimir Fishchenko <hws47a@gmail.com> Date: Sat, 15 Feb 2020 01:23:43 +0000 Subject: [PATCH 633/666] Fix code style issues for Widget Unit Tests --- app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php b/app/code/Magento/Widget/Test/Unit/Helper/ConditionsTest.php index 6c16489924f54..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 { From 339c6f891dacc4536f682aa17971f7918f386265 Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Sat, 15 Feb 2020 14:11:25 +0200 Subject: [PATCH 634/666] small CR fixes, void return type was added --- .../ProductAttributeFormBuildFrontTabObserverTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 index 42092a40a7679..1541bee97efb3 100644 --- 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 @@ -46,7 +46,7 @@ class ProductAttributeFormBuildFrontTabObserverTest extends TestCase /** * @inheritDoc */ - protected function setUp() + protected function setUp(): void { $this->optionListLock = $this->createMock(Yesno::class); $this->moduleManagerMock = $this->createMock(Manager::class); @@ -68,7 +68,7 @@ protected function setUp() /** * Test case when module output is disabled */ - public function testExecuteWhenOutputDisabled() + public function testExecuteWhenOutputDisabled(): void { $this->moduleManagerMock->expects($this->once()) ->method('isOutputEnabled') @@ -83,7 +83,7 @@ public function testExecuteWhenOutputDisabled() /** * Test case when module output is enabled */ - public function testExecuteWhenOutputEnabled() + public function testExecuteWhenOutputEnabled(): void { $this->moduleManagerMock->expects($this->once()) ->method('isOutputEnabled') @@ -91,7 +91,7 @@ public function testExecuteWhenOutputEnabled() ->willReturn(true); $fieldsetMock = $this->createMock(Fieldset::class); - $fieldsetMock->expects(self::exactly(3))->method('addField'); + $fieldsetMock->expects($this->exactly(3))->method('addField'); $formMock = $this->createMock(Form::class); $formMock->expects($this->once()) ->method('getElement') From dfdb396d3ead59c40e05a555e59c58d7cd8919d0 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 17 Feb 2020 10:36:39 +0200 Subject: [PATCH 635/666] add return statement to render method, remove changes from EavSetup.php --- app/code/Magento/Eav/Setup/EavSetup.php | 4 ++-- app/code/Magento/Ui/Component/AbstractComponent.php | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Eav/Setup/EavSetup.php b/app/code/Magento/Eav/Setup/EavSetup.php index 9e2eda92d66ce..d440a84fc8e65 100644 --- a/app/code/Magento/Eav/Setup/EavSetup.php +++ b/app/code/Magento/Eav/Setup/EavSetup.php @@ -797,7 +797,7 @@ private function _getValue($array, $key, $default = null) if (isset($array[$key]) && is_bool($array[$key])) { $array[$key] = (int)$array[$key]; } - return $array[$key] ?? $default; + return isset($array[$key]) ? $array[$key] : $default; } /** @@ -1102,7 +1102,7 @@ public function getAttribute($entityTypeId, $id, $field = null) $row = $setupCache->get($mainTable, $entityTypeId, $id); if ($field !== null) { - return $row[$field] ?? false; + return isset($row[$field]) ? $row[$field] : false; } return $row; diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index 90c73f718426c..9ce6d7d7fd334 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -5,14 +5,12 @@ */ 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 /** @@ -142,10 +140,12 @@ protected function prepareChildComponent(UiComponentInterface $component) /** * Produce and return block's html output + * + * @return string */ public function toHtml() { - $this->render(); + return $this->render(); } /** From 1f882263fdce77c75119466988e7488134912a95 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Mon, 17 Feb 2020 10:47:11 +0200 Subject: [PATCH 636/666] small improvements --- app/code/Magento/Analytics/ReportXml/QueryFactory.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Analytics/ReportXml/QueryFactory.php b/app/code/Magento/Analytics/ReportXml/QueryFactory.php index a54990a1a035d..285ddb1f99e29 100644 --- a/app/code/Magento/Analytics/ReportXml/QueryFactory.php +++ b/app/code/Magento/Analytics/ReportXml/QueryFactory.php @@ -1,5 +1,4 @@ <?php - /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. @@ -9,9 +8,9 @@ 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; -use Magento\Framework\DB\Select; /** * Creates Query object according to configuration From 111a5627a0cf7461a3370b0723ab7449a6e8731c Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Mon, 17 Feb 2020 11:08:09 +0200 Subject: [PATCH 637/666] Unit test for Magento\GiftMessage\Model\Plugin\MergeQuoteItems --- .../Unit/Model/Plugin/MergeQuoteItemsTest.php | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 app/code/Magento/GiftMessage/Test/Unit/Model/Plugin/MergeQuoteItemsTest.php 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) + ); + } +} From 4680f700a448c9eb2bf2172b349c95b3b5c8a4ae Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 14 Feb 2020 17:56:15 +0200 Subject: [PATCH 638/666] fix mftf --- ...uctWithSpecialAndTierDiscountPriceTest.xml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml index 2071f32f20cef..6817969de65c3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontSimpleProductWithSpecialAndTierDiscountPriceTest.xml @@ -26,22 +26,27 @@ <createData entity="tierProductPriceDiscount" stepKey="addTierPrice"> <requiredEntity createDataKey="createProduct"/> </createData> - - <createData entity="specialProductPrice2" stepKey="addSpecialToSimpleProduct"> - <requiredEntity createDataKey="createProduct"/> - <field key="price">65.00</field> - </createData> - <magentoCLI command="cron:run --group=index" stepKey="runCronIndex"/> </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> - <waitForPageLoad stepKey="waitForProductPageLoad"/> <actionGroup ref="AssertStorefrontProductDetailPageNameActionGroup" stepKey="assertProductNameText"> <argument name="productName" value="$createProduct.name$"/> From f8a929e50c75873d82f07c973faf177f612ddad8 Mon Sep 17 00:00:00 2001 From: "ivan.pletnyov" <ivan.pletnyov@transoftgroup.com> Date: Mon, 17 Feb 2020 13:13:38 +0200 Subject: [PATCH 639/666] MC-31524: Create/update customer address via customer repository --- .../Model/Address/CreateAddressTest.php | 44 ++++--- .../Model/Address/DeleteAddressTest.php | 6 +- .../Model/Address/UpdateAddressTest.php | 12 +- .../CustomerRepository/CreateAddressTest.php | 69 +++++++++++ .../CustomerRepository/DeleteAddressTest.php | 42 +++++++ .../CustomerRepository/UpdateAddressTest.php | 107 ++++++++++++++++++ 6 files changed, 247 insertions(+), 33 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/CreateAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/DeleteAddressTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Model/ResourceModel/CustomerRepository/UpdateAddressTest.php diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php index ae65c32fe3f43..c6e1a9bbf8ac5 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/CreateAddressTest.php @@ -38,7 +38,7 @@ class CreateAddressTest extends TestCase AddressInterface::COUNTRY_ID => 'US', 'custom_region_name' => 'Alabama', AddressInterface::CITY => 'CityM', - AddressInterface::STREET => 'Green str, 67', + AddressInterface::STREET => ['Green str, 67'], AddressInterface::LASTNAME => 'Smith', AddressInterface::FIRSTNAME => 'John', ]; @@ -46,42 +46,42 @@ class CreateAddressTest extends TestCase /** * @var ObjectManager */ - private $objectManager; + protected $objectManager; /** - * @var GetRegionIdByName + * @var AddressInterfaceFactory */ - private $getRegionIdByName; + protected $addressFactory; /** - * @var AddressInterfaceFactory + * @var CustomerRegistry */ - private $addressFactory; + protected $customerRegistry; /** - * @var AddressRegistry + * @var AddressRepositoryInterface */ - private $addressRegistry; + protected $addressRepository; /** - * @var Address + * @var GetRegionIdByName */ - private $addressResource; + protected $getRegionIdByName; /** - * @var CustomerRegistry + * @var CustomerRepositoryInterface */ - private $customerRegistry; + protected $customerRepository; /** - * @var AddressRepositoryInterface + * @var AddressRegistry */ - private $addressRepository; + private $addressRegistry; /** - * @var CustomerRepositoryInterface + * @var Address */ - private $customerRepository; + private $addressResource; /** * @var int[] @@ -94,13 +94,13 @@ class CreateAddressTest extends TestCase protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); - $this->getRegionIdByName = $this->objectManager->get(GetRegionIdByName::class); $this->addressFactory = $this->objectManager->get(AddressInterfaceFactory::class); - $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->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(); } @@ -310,10 +310,6 @@ public function createWrongAddressesDataProvider(): array array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::LASTNAME => '']), InputException::requiredField('lastname'), ], - 'required_field_empty_street_as_string' => [ - array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => '']), - InputException::requiredField('street'), - ], 'required_field_empty_street_as_array' => [ array_replace(self::STATIC_CUSTOMER_ADDRESS_DATA, [AddressInterface::STREET => []]), InputException::requiredField('street'), @@ -339,7 +335,7 @@ public function createWrongAddressesDataProvider(): array * @param bool $isDefaultBilling * @return AddressInterface */ - private function createAddress( + protected function createAddress( int $customerId, array $addressData, bool $isDefaultShipping = false, diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php index fe5437e294fc6..b303e8b0d1ca7 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/DeleteAddressTest.php @@ -30,17 +30,17 @@ class DeleteAddressTest extends TestCase /** * @var CustomerRegistry */ - private $customerRegistry; + protected $customerRegistry; /** * @var AddressRepositoryInterface */ - private $addressRepository; + protected $addressRepository; /** * @var CustomerRepositoryInterface */ - private $customerRepository; + protected $customerRepository; /** * @inheritdoc diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php index 8867f269cdf37..902c9ae2407a7 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/Address/UpdateAddressTest.php @@ -33,32 +33,32 @@ class UpdateAddressTest extends TestCase /** * @var AddressRegistry */ - private $addressRegistry; + protected $addressRegistry; /** * @var Address */ - private $addressResource; + protected $addressResource; /** * @var CustomerRegistry */ - private $customerRegistry; + protected $customerRegistry; /** * @var AddressRepositoryInterface */ - private $addressRepository; + protected $addressRepository; /** * @var CustomerRepositoryInterface */ - private $customerRepository; + protected $customerRepository; /** * @var int[] */ - private $processedAddressesIds = []; + protected $processedAddressesIds = []; /** * @inheritdoc 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); + } +} From 86a3efa349345b9c0b068d1ea54be91bc1f8829c Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Mon, 17 Feb 2020 14:24:10 +0200 Subject: [PATCH 640/666] Update for the latest changes --- .../Test/Unit/Model/Js/DataProviderTest.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 c9a0dc2373697..be52c6a744c50 100644 --- a/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php +++ b/app/code/Magento/Translation/Test/Unit/Model/Js/DataProviderTest.php @@ -191,7 +191,7 @@ public function configDataProvider(): array [ 'patterns' => [ '~\$\.mage\.__\(([\'"])(.+?)\1\)~', - '~i18n\:\s*(["\'])(.*?)(?<!\\\)\1~', + '~(?:i18n\:|_\.i18n\()\s*(["\'])(.*?)(?<!\\\\)\1~', '~translate\=("\')([^\'].*?)\'\"~', '~(?s)\$t\(\s*([\'"])(\?\<translate\>.+?)(?<!\\\)\1\s*(*SKIP)\)(?s)~', '~translate args\=("|\'|"\'|\\\"\')([^\'].*?)(\'\\\"|\'"|\'|")~', @@ -201,18 +201,22 @@ public function configDataProvider(): array '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', - 'content2$.mage.__("hello3")content3', + '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'], ] ], ] From eb81164728796817fa26563620a2b3594b6e71d8 Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Mon, 17 Feb 2020 13:53:01 +0100 Subject: [PATCH 641/666] Swatches eliminate objects instantiation --- app/code/Magento/Swatches/Helper/Data.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index f9a600925b2a9..688a88a2dd5da 100644 --- a/app/code/Magento/Swatches/Helper/Data.php +++ b/app/code/Magento/Swatches/Helper/Data.php @@ -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; } } From 2e1b0f62633ae1e4b7123ba8a4e83de9e5df95ab Mon Sep 17 00:00:00 2001 From: tufa <tufa.hu@gmail.com> Date: Mon, 17 Feb 2020 14:10:59 +0100 Subject: [PATCH 642/666] toHtml should return an empty string when Msrp price is applicable --- .../Unit/Pricing/Render/TierPriceBoxTest.php | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php 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..aa3d5bcd3c569 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php @@ -0,0 +1,113 @@ +<?php +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() + { + $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() + { + $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); + } +} From 1a54c8a26cb87edfdf046ce815650e2091fe929a Mon Sep 17 00:00:00 2001 From: tufa <tufa.hu@gmail.com> Date: Mon, 17 Feb 2020 15:57:22 +0100 Subject: [PATCH 643/666] add copyright text --- .../Test/Unit/Pricing/Render/TierPriceBoxTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php index aa3d5bcd3c569..95f592daaa06a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/TierPriceBoxTest.php @@ -1,4 +1,8 @@ <?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ declare(strict_types=1); namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Render; @@ -61,7 +65,7 @@ class TierPriceBoxTest extends \PHPUnit\Framework\TestCase /** * @inheritDoc */ - protected function setUp() + protected function setUp(): void { $this->context = $this->createPartialMock(Context::class, []); $this->saleableItem = $this->createPartialMock(Product::class, ['getPriceInfo']); @@ -85,7 +89,7 @@ protected function setUp() ); } - public function testToHtmlEmptyWhenMsrpPriceIsApplicable() + public function testToHtmlEmptyWhenMsrpPriceIsApplicable(): void { $msrpPriceMock = $this->createPartialMock( MsrpPrice::class, From abad45200d75685b70aa06fc04c3ee9b6327d17e Mon Sep 17 00:00:00 2001 From: Karyna Tsymbal <k.tsymbal@atwix.com> Date: Mon, 17 Feb 2020 17:03:08 +0200 Subject: [PATCH 644/666] Unit test for Magento\Vault\Plugin\PaymentVaultAttributesLoad --- .../Plugin/PaymentVaultAttributesLoadTest.php | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultAttributesLoadTest.php 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 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Vault\Test\Unit\Plugin; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Sales\Api\Data\OrderPaymentExtensionFactory; +use Magento\Sales\Api\Data\OrderPaymentExtensionInterface; +use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Vault\Api\Data\PaymentTokenInterface; +use Magento\Vault\Api\PaymentTokenManagementInterface; +use Magento\Vault\Plugin\PaymentVaultAttributesLoad; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit Test for \Magento\Vault\Plugin\PaymentVaultAttributesLoad + */ +class PaymentVaultAttributesLoadTest extends TestCase +{ + /** + * @var OrderPaymentExtensionFactory|MockObject + */ + private $paymentExtensionFactoryMock; + + /** + * @var PaymentTokenManagementInterface|MockObject + */ + private $paymentTokenManagementMock; + + /** + * @var OrderPaymentInterface|MockObject + */ + private $paymentMock; + + /** + * @var OrderPaymentExtensionInterface|MockObject + */ + private $paymentExtensionMock; + + /** + * @var PaymentVaultAttributesLoad + */ + private $plugin; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->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) + ); + } +} From ee6d8916cf0b823ce0ef8c7f97e7aa41ab11ceb2 Mon Sep 17 00:00:00 2001 From: tufa <tufa.hu@gmail.com> Date: Mon, 17 Feb 2020 18:35:28 +0100 Subject: [PATCH 645/666] remove @package tag --- .../Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php index 0ac4642eff8a2..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 { From 6ed0d87d0182423e201a6616ad87e58e86278de3 Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Mon, 17 Feb 2020 20:21:22 +0100 Subject: [PATCH 646/666] Tests fix --- app/code/Magento/Swatches/Helper/Data.php | 2 +- .../Swatches/Test/Unit/Helper/DataTest.php | 55 +++++++------------ 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/app/code/Magento/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index 688a88a2dd5da..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; diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php index aa44f1f114037..fbcb3c193696f 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 = [ [ @@ -742,23 +740,16 @@ public function testGetSwatchesByOptionsIdIf2() $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, - ] - ); + $swatchMock->expects($this->at(4))->method('offsetGet')->with('type')->willReturn(0); + $swatchMock->expects($this->at(5))->method('offsetGet')->with('store_id')->willReturn(1); + $swatchMock->expects($this->at(6))->method('offsetGet')->with('value')->willReturn('test2'); + $swatchMock->expects($this->at(7))->method('offsetGet')->with('option_id')->willReturn(36); + + $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, @@ -783,17 +775,12 @@ public function testGetSwatchesByOptionsIdIf3() $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, - ] - ); + $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); From 7e3390dd86faf45018a18e5f76d0ebe067019186 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Mon, 17 Feb 2020 21:25:25 +0200 Subject: [PATCH 647/666] magento/magento2#25806 Reflection: Fix null as first return type --- lib/internal/Magento/Framework/Reflection/TypeProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php index 49ba98de83e14..11c9e605577b1 100644 --- a/lib/internal/Magento/Framework/Reflection/TypeProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/TypeProcessor.php @@ -288,7 +288,7 @@ public function getGetterReturnType($methodReflection) $types = $returnAnnotation->getTypes(); $returnType = null; foreach ($types as $type) { - if ($type != 'null') { + if ($type !== 'null') { $returnType = $type; break; } From f894321ca02705f8131579a224a1c416669a5a1c Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Fri, 3 Jan 2020 15:32:57 +0200 Subject: [PATCH 648/666] refactor integration tests, change fixtures --- .../Model/Sequence/DeleteByStore.php | 2 +- .../Observer/SequenceRemovalObserver.php | 2 +- .../Unit/Model/Sequence/DeleteByStoreTest.php | 2 +- .../Magento/TestFramework/Application.php | 2 +- .../Magento/Catalog/Model/Product/UrlTest.php | 2 +- .../Magento/Store/Model/StoreTest.php | 23 ++++++++++--------- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php index 7e6ef8b2f3dda..e86cc8b1b2e6d 100644 --- a/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php +++ b/app/code/Magento/SalesSequence/Model/Sequence/DeleteByStore.php @@ -12,7 +12,7 @@ use Magento\SalesSequence\Model\ResourceModel\Meta as ResourceMetadata; /** - * Class DeleteByStore + * Delete Sequence by Store. */ class DeleteByStore { diff --git a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php index 4ed4752b27150..c10ef80f6eb9b 100644 --- a/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php +++ b/app/code/Magento/SalesSequence/Observer/SequenceRemovalObserver.php @@ -12,7 +12,7 @@ use Magento\SalesSequence\Model\Sequence\DeleteByStore; /** - * Class SequenceRemovalObserver + * Observer for Sequence Removal. */ class SequenceRemovalObserver implements ObserverInterface { diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php index 1b652ac99b866..17dbd6c37265f 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/Sequence/DeleteByStoreTest.php @@ -17,7 +17,7 @@ use PHPUnit\Framework\TestCase; /** - * Class DeleteByStoreTest + * Test for \Magento\SalesSequence\Model\Sequence\DeleteByStore class. */ class DeleteByStoreTest extends TestCase { 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/testsuite/Magento/Catalog/Model/Product/UrlTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php index 1725b15346435..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 enabled * @dataProvider getUrlsWithSecondStoreProvider + * @magentoDbIsolation disabled * @magentoAppArea adminhtml */ public function testGetUrlInStoreWithSecondStore($storeCode, $expectedProductUrl) diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php index 4a670f39f4e01..58c7d1cba45fe 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreTest.php @@ -278,8 +278,8 @@ 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() { @@ -318,8 +318,9 @@ public function testGetCurrentUrl() } /** - * @magentoDataFixture Magento/Store/_files/second_store.php - * @magentoDataFixture Magento/Catalog/_files/category_product.php + * @magentoDataFixture Magento/Store/_files/core_second_third_fixturestore.php + * @magentoDataFixture Magento/Catalog/_files/products.php + * @magentoAppIsolation enabled * @magentoDbIsolation enabled */ public function testGetCurrentUrlWithUseStoreInUrlFalse() @@ -329,34 +330,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) ); } From 90436f68b524be4d1d467c2032604fe877f1de63 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Tue, 18 Feb 2020 10:31:18 +0200 Subject: [PATCH 649/666] MC-31526: Indexer price calculation for fixed/dynamic bundle product with different type prices --- .../Bundle/Model/Product/PriceTest.php | 525 +++++++++++++++++- ...namic_bundle_product_with_catalog_rule.php | 117 ++++ ...dle_product_with_catalog_rule_rollback.php | 57 ++ ...amic_bundle_product_with_special_price.php | 70 +++ ...le_product_with_special_price_rollback.php | 23 + ...dynamic_bundle_product_with_tier_price.php | 94 ++++ ...undle_product_with_tier_price_rollback.php | 23 + ...namic_bundle_product_without_discounts.php | 69 +++ ...dle_product_without_discounts_rollback.php | 23 + ...ixed_bundle_product_with_special_price.php | 77 +++ ...le_product_with_special_price_rollback.php | 23 + .../fixed_bundle_product_with_tier_price.php | 101 ++++ ...undle_product_with_tier_price_rollback.php | 23 + ...fixed_bundle_product_without_discounts.php | 76 +++ ...dle_product_without_discounts_rollback.php | 23 + ...category_with_different_price_products.php | 24 +- .../_files/catalog_rule_for_category_999.php | 59 ++ ...catalog_rule_for_category_999_rollback.php | 28 + 18 files changed, 1400 insertions(+), 35 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_catalog_rule_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_special_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_with_tier_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/dynamic_bundle_product_without_discounts_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_special_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_with_tier_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/fixed_bundle_product_without_discounts_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_for_category_999_rollback.php 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/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/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/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(); From 18eaad44caa56f3913389486b6722715392b4a27 Mon Sep 17 00:00:00 2001 From: DmytroPaidych <dimonovp@gmail.com> Date: Tue, 18 Feb 2020 10:32:50 +0200 Subject: [PATCH 650/666] MC-31528: Admin: Mass actions on customers grid --- .../Adminhtml/Index/InlineEditTest.php | 153 ++++++++++++++++++ .../Adminhtml/Index/MassUnsubscribeTest.php | 91 +++++++++++ .../Newsletter/_files/three_subscribers.php | 18 +++ .../_files/three_subscribers_rollback.php | 8 + 4 files changed, 270 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/InlineEditTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/Index/MassUnsubscribeTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers.php create mode 100644 dev/tests/integration/testsuite/Magento/Newsletter/_files/three_subscribers_rollback.php 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/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'; From d0f3da81c67f56e817cc85ae5e4cf954466ffe5f Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 18 Feb 2020 10:34:59 +0200 Subject: [PATCH 651/666] MC-31521: Customer login on storefront --- .../Magento/Customer/Block/Form/LoginTest.php | 92 ++++++++++ .../Controller/Account/LoginPostTest.php | 171 ++++++++++++++++++ .../Customer/Controller/AccountTest.php | 115 ------------ .../Customer/_files/unconfirmed_customer.php | 47 +++++ .../_files/unconfirmed_customer_rollback.php | 33 ++++ 5 files changed, 343 insertions(+), 115 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Block/Form/LoginTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Controller/Account/LoginPostTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer_rollback.php 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/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 18f9b2d2cb737..076f9585788cc 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. */ @@ -640,35 +606,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. * @@ -915,20 +852,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 @@ -997,44 +920,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/_files/unconfirmed_customer.php b/dev/tests/integration/testsuite/Magento/Customer/_files/unconfirmed_customer.php new file mode 100644 index 0000000000000..3aad592ad34ef --- /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); From 1d2dd67de672cfaae56e91e533e0933226129fe4 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 18 Feb 2020 10:47:10 +0200 Subject: [PATCH 652/666] Adding article as an additional supported layout tag --- .../View/Layout/Generator/Container.php | 1 + .../Unit/Layout/Generator/ContainerTest.php | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/Container.php b/lib/internal/Magento/Framework/View/Layout/Generator/Container.php index d220808e21455..8e906f3c03618 100644 --- a/lib/internal/Magento/Framework/View/Layout/Generator/Container.php +++ b/lib/internal/Magento/Framework/View/Layout/Generator/Container.php @@ -39,6 +39,7 @@ class Container implements Layout\GeneratorInterface 'table', 'tfoot', 'ul', + 'article', ]; /** 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, ] ]; } From 7fa4a1da037ba265cf510c732bb2abb2c89a2978 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 18 Feb 2020 12:32:13 +0200 Subject: [PATCH 653/666] MC-31444: [FT] [MFTF] [2.4] Fix flaky test StorefrontTaxInformationInShoppingCartForCustomerVirtualQuoteTest (MC-41933) --- ...formationInShoppingCartForCustomerPhysicalQuoteTest.xml | 7 ++----- ...nformationInShoppingCartForCustomerVirtualQuoteTest.xml | 2 +- ...xInformationInShoppingCartForGuestPhysicalQuoteTest.xml | 7 ++----- ...axInformationInShoppingCartForGuestVirtualQuoteTest.xml | 2 +- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml index d0c3f517137d6..a43f8a306902f 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerPhysicalQuoteTest.xml @@ -16,7 +16,7 @@ <description value="Tax information are updating/recalculating on fly in shopping cart for Customer with default addresses (physical quote)"/> <severity value="CRITICAL"/> <useCaseId value="MC-294"/> - <testCaseId value="MC-16526"/> + <testCaseId value="MC-28586"/> <group value="checkout"/> <group value="tax"/> <group value="weee"/> @@ -36,10 +36,8 @@ <!-- 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"/> @@ -71,7 +69,6 @@ <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"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> diff --git a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml index 04c100e8413d5..7c6394e6f8848 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForCustomerVirtualQuoteTest.xml @@ -16,7 +16,7 @@ <description value="Tax information are updating/recalculating on fly in shopping cart for Customer with default addresses (virtual quote)"/> <severity value="CRITICAL"/> <useCaseId value="MC-294"/> - <testCaseId value="MC-16525"/> + <testCaseId value="MC-28585"/> <group value="checkout"/> <group value="tax"/> <group value="weee"/> diff --git a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml index 08a234368754d..7a1077675cbee 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestPhysicalQuoteTest.xml @@ -16,7 +16,7 @@ <description value="Tax information are updating/recalculating on fly in shopping cart for Guest (physical quote)"/> <severity value="CRITICAL"/> <useCaseId value="MC-294"/> - <testCaseId value="MC-16538"/> + <testCaseId value="MC-28592"/> <group value="checkout"/> <group value="tax"/> <group value="weee"/> @@ -36,10 +36,8 @@ <!-- 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="GoToProductPageViaIDActionGroup" stepKey="openProductEditPage"> @@ -66,7 +64,6 @@ <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"/> <amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductsGridFilters"/> diff --git a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml index 22f25e1a2a736..a7059fcfb4644 100644 --- a/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml +++ b/app/code/Magento/Weee/Test/Mftf/Test/StorefrontFPTTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml @@ -16,7 +16,7 @@ <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-11946"/> + <testCaseId value="MC-26557"/> <group value="checkout"/> <group value="tax"/> <group value="weee"/> From 023b240731dbb4aa2e33e36c8e1f83049cd35982 Mon Sep 17 00:00:00 2001 From: Stanislav Ilnytskyi <stailx1@gmail.com> Date: Tue, 18 Feb 2020 12:15:45 +0100 Subject: [PATCH 654/666] static test fix --- .../Swatches/Test/Unit/Helper/DataTest.php | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php index fbcb3c193696f..1b4ab2f4c203b 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php @@ -735,16 +735,16 @@ 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('offsetGet')->with('type')->willReturn(0); - $swatchMock->expects($this->at(5))->method('offsetGet')->with('store_id')->willReturn(1); - $swatchMock->expects($this->at(6))->method('offsetGet')->with('value')->willReturn('test2'); - $swatchMock->expects($this->at(7))->method('offsetGet')->with('option_id')->willReturn(36); - + // @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); @@ -770,12 +770,12 @@ 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); - + // @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); From 0216e5e80f0004f05db2a7f4ad39e86801cdf85b Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Tue, 18 Feb 2020 16:24:17 +0200 Subject: [PATCH 655/666] fix integration test --- .../Pricing/Render/CombinationWithDifferentTypePricesTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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, From da37605cd1aca42e28eb3bffb59499acfa9bab16 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Tue, 18 Feb 2020 16:28:16 +0200 Subject: [PATCH 656/666] Fixing static and integration tests --- .../testsuite/Magento/Framework/View/LayoutTest.php | 2 +- .../Framework/View/Layout/Generator/Container.php | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) 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/lib/internal/Magento/Framework/View/Layout/Generator/Container.php b/lib/internal/Magento/Framework/View/Layout/Generator/Container.php index 8e906f3c03618..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 { /**#@+ @@ -43,7 +46,7 @@ class Container implements Layout\GeneratorInterface ]; /** - * {@inheritdoc} + * @inheritdoc * * @return string */ @@ -96,8 +99,12 @@ public function generateContainer( } /** + * Validate container options + * * @param array $options + * * @return void + * * @throws \Magento\Framework\Exception\LocalizedException */ protected function validateOptions($options) From 36c006f900f84901c9d6c57b4634c6e8de666168 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Tue, 18 Feb 2020 17:05:17 -0600 Subject: [PATCH 657/666] Update QuoteItemQtyListTest.php --- .../Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php | 2 ++ 1 file changed, 2 insertions(+) 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 index 5966b530f72e1..823b0815b29a3 100644 --- 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 @@ -12,6 +12,8 @@ /** * Class QuoteItemQtyListTest + * + * Test for QuoteItemQtyList class */ class QuoteItemQtyListTest extends TestCase { From 352bf4f8328499cce17428086b5bee9e0e0cf361 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Tue, 18 Feb 2020 17:06:39 -0600 Subject: [PATCH 658/666] Fix static --- .../Model/Entity/Collection/AbstractCollectionTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 d3e8ce29cbc61..0194f2db309a6 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,6 +8,7 @@ /** * AbstractCollection test * + * Test for AbstractCollection class * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AbstractCollectionTest extends \PHPUnit\Framework\TestCase @@ -237,7 +238,11 @@ public function testAttributeIdIsInt($values) $_selectAttributesActualValue = $this->readAttribute($this->model, '_selectAttributes'); - $this->assertAttributeEquals([self::ATTRIBUTE_CODE => self::ATTRIBUTE_ID_STRING], '_selectAttributes', $this->model); + $this->assertAttributeEquals( + [self::ATTRIBUTE_CODE => self::ATTRIBUTE_ID_STRING], + '_selectAttributes', + $this->model + ); $this->assertSame($_selectAttributesActualValue[self::ATTRIBUTE_CODE], self::ATTRIBUTE_ID_INT); } From db0201317dc2afa738eb2ba940e11e9eb5ff1fd5 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 19 Feb 2020 18:20:49 +0200 Subject: [PATCH 659/666] Coverage mftf test --- ...nerateProductsOrderedReportActionGroup.xml | 24 ++++++ .../Reports/Test/Mftf/Page/SoldReportPage.xml | 12 +++ .../Mftf/Section/SoldReportMainSection.xml | 17 ++++ .../AdminReportsOrderedGroupedBySkuTest.xml | 78 +++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGenerateProductsOrderedReportActionGroup.xml create mode 100644 app/code/Magento/Reports/Test/Mftf/Page/SoldReportPage.xml create mode 100644 app/code/Magento/Reports/Test/Mftf/Section/SoldReportMainSection.xml create mode 100644 app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedGroupedBySkuTest.xml 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/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/AdminReportsOrderedGroupedBySkuTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminReportsOrderedGroupedBySkuTest.xml new file mode 100644 index 0000000000000..d507d6b38f74b --- /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="logout" 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> From e2e0cc7952f7f171ed9642e0d200317e544ddd12 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Wed, 19 Feb 2020 15:58:23 -0600 Subject: [PATCH 660/666] Fix `StorefrontLoggedInCustomerCreateOrderAllOptionQuantityConfigurableProductCustomStock` test --- .../Test/Mftf/Section/StorefrontProductInfoMainSection.xml | 1 + 1 file changed, 1 insertion(+) 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"/> From 5bd23493e4227fc951fd71e5181b40d5e1c83463 Mon Sep 17 00:00:00 2001 From: Mykhailo Matiola <mykhailo.matiola@transoftgroup.com> Date: Thu, 20 Feb 2020 09:13:09 +0200 Subject: [PATCH 661/666] MC-31531: Storefront: View configurable product with related, up-sells products --- .../Block/Product/ProductList/RelatedTest.php | 114 ++++++++++++++++++ .../Block/Product/ProductList/UpsellTest.php | 43 +++++++ 2 files changed, 157 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/RelatedTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Block/Product/ProductList/UpsellTest.php 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(); + } +} From 0016f9d7c5d37d0a2efef9c750d8bad08380cb2b Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Thu, 20 Feb 2020 09:41:22 -0600 Subject: [PATCH 662/666] Fix static --- .../Model/Quote/Item/QuantityValidator/QuoteItemQtyListTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 823b0815b29a3..59a391581fb06 100644 --- 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 @@ -12,7 +12,7 @@ /** * Class QuoteItemQtyListTest - * + * * Test for QuoteItemQtyList class */ class QuoteItemQtyListTest extends TestCase From be1de052dfdd88493aa0e8c9ad456f5796bc17af Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets <vzaets@magento.com> Date: Thu, 20 Feb 2020 09:42:13 -0600 Subject: [PATCH 663/666] Fix static --- .../Unit/Model/Entity/Collection/AbstractCollectionTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 0194f2db309a6..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 @@ -239,8 +239,8 @@ public function testAttributeIdIsInt($values) $_selectAttributesActualValue = $this->readAttribute($this->model, '_selectAttributes'); $this->assertAttributeEquals( - [self::ATTRIBUTE_CODE => self::ATTRIBUTE_ID_STRING], - '_selectAttributes', + [self::ATTRIBUTE_CODE => self::ATTRIBUTE_ID_STRING], + '_selectAttributes', $this->model ); $this->assertSame($_selectAttributesActualValue[self::ATTRIBUTE_CODE], self::ATTRIBUTE_ID_INT); From 5c0b2207c93dccb6286a3b7f67435b06f84b2933 Mon Sep 17 00:00:00 2001 From: Lena Orobei <oorobei@magento.com> Date: Thu, 20 Feb 2020 10:52:15 -0600 Subject: [PATCH 664/666] Add AdminCreateCmsBlockWithMarginalSpaceTest to the WYSIWYGDisabled group --- .../Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml index 0399d0eb3ab28..f0e68dc1b056b 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml @@ -16,6 +16,7 @@ <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="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> From 23b2279d2783b65c6380cd20210bfa2f250aeb6b Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 20 Feb 2020 18:30:18 -0600 Subject: [PATCH 665/666] MQE-2003: Bump MFTF version in Magento fixed flaky test --- .../Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml index 685385382027b..3a39fe3218d96 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml @@ -20,6 +20,7 @@ <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"/> + <scrollTo selector="{{BlockContentSection.TextArea}}" stepKey="scrollToContentField"/> <fillField selector="{{BlockContentSection.TextArea}}" userInput="{{cmsBlockDataContent}}" stepKey="fillContentField"/> </actionGroup> </actionGroups> From 1ebf6fa78f9b2d6c04197cb11a04f4c43df4fee5 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Fri, 21 Feb 2020 00:35:31 -0600 Subject: [PATCH 666/666] MQE-2003: Bump MFTF version in Magento Added WYSIWYGDisabled group --- .../Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml | 1 - app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml | 2 +- .../Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml | 2 +- app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml | 2 +- .../Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml index 3a39fe3218d96..685385382027b 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminFillCmsBlockFormActionGroup.xml @@ -20,7 +20,6 @@ <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"/> - <scrollTo selector="{{BlockContentSection.TextArea}}" stepKey="scrollToContentField"/> <fillField selector="{{BlockContentSection.TextArea}}" userInput="{{cmsBlockDataContent}}" stepKey="fillContentField"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml index 6867560551915..7e7d942140645 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockTest.xml @@ -17,10 +17,10 @@ <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"/> </before> <after> <actionGroup ref="deleteBlock" stepKey="deleteCreatedBlock"> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml index 0399d0eb3ab28..97fac85aac81c 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsBlockWithMarginalSpaceTest.xml @@ -16,10 +16,10 @@ <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="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> </before> <amOnPage url="{{CmsNewBlock.url}}" stepKey="amOnBlocksCreationForm"/> <waitForPageLoad stepKey="waitForPageLoad1"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml index 7fd39ab5bb1d6..82bcb295c2a9a 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateCmsPageTest.xml @@ -17,10 +17,10 @@ <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"/> </before> <after> <actionGroup ref="logout" stepKey="adminLogout"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml index cf333f8b559d0..5c5fccf761aa1 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCreateDuplicatedCmsPageTest.xml @@ -17,10 +17,10 @@ <severity value="CRITICAL"/> <testCaseId value="MAGETWO-89184"/> <group value="Cms"/> + <group value="WYSIWYGDisabled"/> </annotations> <before> <actionGroup ref="LoginActionGroup" stepKey="loginGetFromGeneralFile"/> - <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> </before> <after> <actionGroup ref="logout" stepKey="logout"/>