From 891198c5117d4d2345b66745f86bfdfca1978525 Mon Sep 17 00:00:00 2001 From: nikunj Date: Wed, 20 Mar 2019 18:16:44 +0530 Subject: [PATCH 001/242] #21853: Allow mview indexers to use different entity columns. --- .../Framework/Mview/View/Subscription.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 67dff1a2cc5db..6e02f1d169daa 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -117,8 +117,19 @@ public function create() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { + // Store current column name for reverting back later. + $originalColumnName = $this->getColumnName(); + /** @var \Magento\Framework\Mview\ViewInterface $view */ + // Use the column name from specific subscription instead of + // use from the one which is currently updated. + $subscriptions = $view->getSubscriptions(); + $subscription = $subscriptions[$this->getTableName()]; + $this->columnName = $subscription['column']; $trigger->addStatement($this->buildStatement($event, $view->getChangelog())); + + // Revert back the column name. + $this->columnName = $originalColumnName; } $this->connection->dropTrigger($trigger->getName()); @@ -146,8 +157,19 @@ public function remove() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { + // Store current column name for reverting back later. + $originalColumnName = $this->columnName; + /** @var \Magento\Framework\Mview\ViewInterface $view */ + // Use the column name from specific subscription instead of + // use from the one which is currently updated. + $subscriptions = $view->getSubscriptions(); + $subscription = $subscriptions[$this->getTableName()]; + $this->columnName = $subscription['column']; $trigger->addStatement($this->buildStatement($event, $view->getChangelog())); + + // Revert back the column name. + $this->columnName = $originalColumnName; } $this->connection->dropTrigger($trigger->getName()); From b59fc5a549e85d556979b58c42b3cd39058a5a3f Mon Sep 17 00:00:00 2001 From: nikunj Date: Sun, 12 Apr 2020 17:37:36 +0530 Subject: [PATCH 002/242] #21853: Simplify the code change. --- .../Framework/Mview/View/Subscription.php | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 32841bd7e0f9d..3204722a86140 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -113,23 +113,16 @@ public function create() ->setEvent($event) ->setTable($this->resource->getTableName($this->tableName)); - $trigger->addStatement($this->buildStatement($event, $this->getView()->getChangelog())); + $trigger->addStatement($this->buildStatement($event, $this->getView()->getChangelog(), $this->getColumnName())); // Add statements for linked views foreach ($this->getLinkedViews() as $view) { - // Store current column name for reverting back later. - $originalColumnName = $this->getColumnName(); - /** @var \Magento\Framework\Mview\ViewInterface $view */ // Use the column name from specific subscription instead of // use from the one which is currently updated. $subscriptions = $view->getSubscriptions(); $subscription = $subscriptions[$this->getTableName()]; - $this->columnName = $subscription['column']; - $trigger->addStatement($this->buildStatement($event, $view->getChangelog())); - - // Revert back the column name. - $this->columnName = $originalColumnName; + $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); } $this->connection->dropTrigger($trigger->getName()); @@ -157,19 +150,12 @@ public function remove() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { - // Store current column name for reverting back later. - $originalColumnName = $this->columnName; - /** @var \Magento\Framework\Mview\ViewInterface $view */ // Use the column name from specific subscription instead of // use from the one which is currently updated. $subscriptions = $view->getSubscriptions(); $subscription = $subscriptions[$this->getTableName()]; - $this->columnName = $subscription['column']; - $trigger->addStatement($this->buildStatement($event, $view->getChangelog())); - - // Revert back the column name. - $this->columnName = $originalColumnName; + $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); } $this->connection->dropTrigger($trigger->getName()); @@ -216,9 +202,10 @@ protected function getLinkedViews() * * @param string $event * @param \Magento\Framework\Mview\View\ChangelogInterface $changelog + * @param string $subscriptionColumnName * @return string */ - protected function buildStatement($event, $changelog) + protected function buildStatement($event, $changelog, $subscriptionColumnName) { switch ($event) { case Trigger::EVENT_INSERT: @@ -258,7 +245,7 @@ protected function buildStatement($event, $changelog) $trigger, $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())), $this->connection->quoteIdentifier($changelog->getColumnName()), - $this->connection->quoteIdentifier($this->getColumnName()) + $this->connection->quoteIdentifier($subscriptionColumnName) ); } From 4035ec08ada4cb5d5495bc7325a982c81c5c02b3 Mon Sep 17 00:00:00 2001 From: nikunj Date: Sun, 12 Apr 2020 17:40:13 +0530 Subject: [PATCH 003/242] #21853: Correct the comment. --- .../Magento/Framework/Mview/View/Subscription.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 3204722a86140..642f5bc610653 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -118,8 +118,9 @@ public function create() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { /** @var \Magento\Framework\Mview\ViewInterface $view */ - // Use the column name from specific subscription instead of - // use from the one which is currently updated. + // Use the column name from specific linked view instead of + // using from the one which is currently updated for all + // the views. $subscriptions = $view->getSubscriptions(); $subscription = $subscriptions[$this->getTableName()]; $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); @@ -151,8 +152,9 @@ public function remove() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { /** @var \Magento\Framework\Mview\ViewInterface $view */ - // Use the column name from specific subscription instead of - // use from the one which is currently updated. + // Use the column name from specific linked view instead of + // using from the one which is currently updated for all + // the views. $subscriptions = $view->getSubscriptions(); $subscription = $subscriptions[$this->getTableName()]; $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); From 320ced74bdf9e7739d20397b5eff2e8ad98c95f1 Mon Sep 17 00:00:00 2001 From: nikunj Date: Tue, 14 Apr 2020 12:12:03 +0530 Subject: [PATCH 004/242] 21853: Send the view object and do all processing in buildStatement. --- .../Framework/Mview/View/Subscription.php | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 642f5bc610653..cd6288a231eb9 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -113,17 +113,12 @@ public function create() ->setEvent($event) ->setTable($this->resource->getTableName($this->tableName)); - $trigger->addStatement($this->buildStatement($event, $this->getView()->getChangelog(), $this->getColumnName())); + $trigger->addStatement($this->buildStatement($event, $this->getView())); // Add statements for linked views foreach ($this->getLinkedViews() as $view) { /** @var \Magento\Framework\Mview\ViewInterface $view */ - // Use the column name from specific linked view instead of - // using from the one which is currently updated for all - // the views. - $subscriptions = $view->getSubscriptions(); - $subscription = $subscriptions[$this->getTableName()]; - $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); + $trigger->addStatement($this->buildStatement($event, $view)); } $this->connection->dropTrigger($trigger->getName()); @@ -152,12 +147,7 @@ public function remove() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { /** @var \Magento\Framework\Mview\ViewInterface $view */ - // Use the column name from specific linked view instead of - // using from the one which is currently updated for all - // the views. - $subscriptions = $view->getSubscriptions(); - $subscription = $subscriptions[$this->getTableName()]; - $trigger->addStatement($this->buildStatement($event, $view->getChangelog(), $subscription['column'])); + $trigger->addStatement($this->buildStatement($event, $view)); } $this->connection->dropTrigger($trigger->getName()); @@ -203,12 +193,18 @@ protected function getLinkedViews() * Build trigger statement for INSERT, UPDATE, DELETE events * * @param string $event - * @param \Magento\Framework\Mview\View\ChangelogInterface $changelog - * @param string $subscriptionColumnName + * @param \Magento\Framework\Mview\ViewInterface $view * @return string */ - protected function buildStatement($event, $changelog, $subscriptionColumnName) + protected function buildStatement($event, $view) { + // Get the subscription for the specific view and specific table. + // We will use column name from it. + $subscription = $view->getSubscriptions()[$this->getTableName()]; + + // Get the changelog from View to get changelog column name. + $changelog = $view->getChangelog(); + switch ($event) { case Trigger::EVENT_INSERT: $trigger = "INSERT IGNORE INTO %s (%s) VALUES (NEW.%s);"; @@ -247,7 +243,7 @@ protected function buildStatement($event, $changelog, $subscriptionColumnName) $trigger, $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())), $this->connection->quoteIdentifier($changelog->getColumnName()), - $this->connection->quoteIdentifier($subscriptionColumnName) + $this->connection->quoteIdentifier($subscription['column']) ); } From 7c2d2a6774717fe6374df61edd22f39a5c02c733 Mon Sep 17 00:00:00 2001 From: nikunj Date: Sat, 29 Aug 2020 12:02:13 +0530 Subject: [PATCH 005/242] #21853: Fix tests. --- .../Framework/Mview/Test/Unit/View/SubscriptionTest.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php index b91c0b525390f..e0bdf570945a2 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php @@ -220,8 +220,6 @@ public function testCreate() $this->viewMock->expects($this->exactly(3)) ->method('getId') ->willReturn('this_id'); - $this->viewMock->expects($this->never()) - ->method('getSubscriptions'); $this->viewCollectionMock->expects($this->exactly(1)) ->method('getViewsByStateMode') @@ -290,9 +288,7 @@ public function testRemove() $otherViewMock->expects($this->exactly(1)) ->method('getId') ->willReturn('other_id'); - $otherViewMock->expects($this->exactly(1)) - ->method('getSubscriptions') - ->willReturn([['name' => $this->tableName], ['name' => 'otherTableName']]); + $otherViewMock->expects($this->exactly(3)) ->method('getChangelog') ->willReturn($otherChangelogMock); @@ -300,8 +296,6 @@ public function testRemove() $this->viewMock->expects($this->exactly(3)) ->method('getId') ->willReturn('this_id'); - $this->viewMock->expects($this->never()) - ->method('getSubscriptions'); $this->viewCollectionMock->expects($this->exactly(1)) ->method('getViewsByStateMode') From 8388a90ea53e67a3f0bde1e03e2f24b64f1925ee Mon Sep 17 00:00:00 2001 From: nikunj Date: Mon, 31 Aug 2020 11:44:45 +0530 Subject: [PATCH 006/242] #21853: Fix tests. --- .../Magento/Framework/Mview/View/Subscription.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index cd6288a231eb9..a65f6e98016f1 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -178,7 +178,7 @@ protected function getLinkedViews() continue; } // Search in view subscriptions - foreach ($view->getSubscriptions() as $subscription) { + foreach ($view->getSubscriptions() ?? [] as $subscription) { if ($subscription['name'] != $this->getTableName()) { continue; } @@ -200,7 +200,12 @@ protected function buildStatement($event, $view) { // Get the subscription for the specific view and specific table. // We will use column name from it. - $subscription = $view->getSubscriptions()[$this->getTableName()]; + $subscriptions = $view->getSubscriptions() ?? []; + if (empty($subscriptions[$this->getTableName()])) { + return ''; + } + + $subscription = $subscriptions[$this->getTableName()]; // Get the changelog from View to get changelog column name. $changelog = $view->getChangelog(); From ff56be5640ab6654ba677f5fba24f98efa5faacd Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Mon, 28 Sep 2020 16:39:52 +0300 Subject: [PATCH 007/242] magento/magento2#21853: Allow mview indexers to use different entity columns - unit & static tests fix. --- .../Mview/Test/Unit/View/SubscriptionTest.php | 32 +++++++++++++++++-- .../Framework/Mview/View/Subscription.php | 6 ++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php index e0bdf570945a2..dc14cae93ca70 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php @@ -44,7 +44,7 @@ class SubscriptionTest extends TestCase protected $viewMock; /** @var string */ - private $tableName; + private $tableName = 'thisTableName'; protected function setUp(): void { @@ -210,9 +210,14 @@ public function testCreate() $otherViewMock->expects($this->exactly(1)) ->method('getId') ->willReturn('other_id'); - $otherViewMock->expects($this->exactly(1)) + $otherViewMock->expects($this->exactly(4)) ->method('getSubscriptions') - ->willReturn([['name' => $this->tableName], ['name' => 'otherTableName']]); + ->willReturn( + [ + $this->tableName => ['name' => $this->tableName, 'column' => 'columnName'], + 'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName'] + ] + ); $otherViewMock->expects($this->exactly(3)) ->method('getChangelog') ->willReturn($otherChangelogMock); @@ -234,6 +239,17 @@ public function testCreate() ->method('createTrigger') ->with($triggerMock); + $this->tableName = 'thisTableName'; + + $this->viewMock->expects($this->exactly(3)) + ->method('getSubscriptions') + ->willReturn( + [ + $this->tableName => ['name' => $this->tableName, 'column' => 'columnName'], + 'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName'] + ] + ); + $this->model->create(); } @@ -285,6 +301,7 @@ public function testRemove() true, [] ); + $otherViewMock->expects($this->exactly(1)) ->method('getId') ->willReturn('other_id'); @@ -293,6 +310,15 @@ public function testRemove() ->method('getChangelog') ->willReturn($otherChangelogMock); + $otherViewMock->expects($this->any()) + ->method('getSubscriptions') + ->willReturn( + [ + $this->tableName => ['name' => $this->tableName, 'column' => 'columnName'], + 'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName'] + ] + ); + $this->viewMock->expects($this->exactly(3)) ->method('getId') ->willReturn('this_id'); diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index a65f6e98016f1..cfab8b2479bc1 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -11,9 +11,7 @@ use Magento\Framework\Mview\View\StateInterface; /** - * Class Subscription - * - * @package Magento\Framework\Mview\View + * Mview subscription. */ class Subscription implements SubscriptionInterface { @@ -202,7 +200,7 @@ protected function buildStatement($event, $view) // We will use column name from it. $subscriptions = $view->getSubscriptions() ?? []; if (empty($subscriptions[$this->getTableName()])) { - return ''; + return ''; } $subscription = $subscriptions[$this->getTableName()]; From 9ffcdc60c5afa199d760d74e1b127ab69878c703 Mon Sep 17 00:00:00 2001 From: Anna Pak Date: Sun, 4 Oct 2020 15:26:12 +0300 Subject: [PATCH 008/242] refactoring of AdminCreateInvoiceTest --- .../Test/Mftf/Test/AdminCreateInvoiceTest.xml | 93 +++++++------------ 1 file changed, 31 insertions(+), 62 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index 73c126bb7794f..e6a0a8b3661dd 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -18,77 +18,46 @@ - + + - + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - + - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - From 0c14e5ffd0778b5d7d203b3b74deea361a3d3f80 Mon Sep 17 00:00:00 2001 From: Anna Pak Date: Sun, 4 Oct 2020 15:38:27 +0300 Subject: [PATCH 009/242] refactored --- .../Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index e6a0a8b3661dd..f91c8d9993044 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -55,7 +55,7 @@ - + From ea995471fc9a9c0f75ad3dae3cbfbaba215327f0 Mon Sep 17 00:00:00 2001 From: Anna Pak Date: Mon, 5 Oct 2020 13:16:32 +0300 Subject: [PATCH 010/242] wrap openOrder action with ActionGroup Please enter the commit message for your changes. Lines starting --- .../Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index f91c8d9993044..f79154398eaff 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -45,7 +45,9 @@ - + + + From 3e467313566cb38f7af8bb6c5d9b991b35d0dcbe Mon Sep 17 00:00:00 2001 From: Anna Pak Date: Mon, 5 Oct 2020 14:14:04 +0300 Subject: [PATCH 011/242] deprecating old test Please enter the commit message for your changes. Lines starting --- .../Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index f79154398eaff..49ae1844a1cf1 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -8,7 +8,7 @@ - + From 7806115a430973fec96cef5be76de5d30cf81a76 Mon Sep 17 00:00:00 2001 From: Oleh Usik Date: Wed, 4 Nov 2020 12:41:57 +0200 Subject: [PATCH 012/242] Assert discount --- ...ssertStorefrontCartDiscountActionGroup.xml | 21 +++++++++++++++++++ ...tCheckoutWithCouponAndZeroSubtotalTest.xml | 6 ++++-- ...efrontUKCustomerCheckoutWithCouponTest.xml | 6 ++++-- ...eConditionAndFreeShippingIsAppliedTest.xml | 4 +++- ...inCreateCartPriceRuleEmptyFromDateTest.xml | 6 ++++-- ...inCreateCartPriceRuleForCouponCodeTest.xml | 6 ++++-- ...ateCartPriceRuleForGeneratedCouponTest.xml | 6 ++++-- ...talAndVerifyRuleConditionIsAppliedTest.xml | 4 +++- ...oryAndVerifyRuleConditionIsAppliedTest.xml | 4 +++- ...ghtAndVerifyRuleConditionIsAppliedTest.xml | 4 +++- .../StorefrontCartPriceRuleCountryTest.xml | 6 ++++-- .../StorefrontCartPriceRulePostcodeTest.xml | 6 ++++-- .../StorefrontCartPriceRuleQuantityTest.xml | 6 ++++-- .../Test/StorefrontCartPriceRuleStateTest.xml | 6 ++++-- .../StorefrontCartPriceRuleSubtotalTest.xml | 6 ++++-- ...ValueWithFullDiscountUsingCartRuleTest.xml | 6 ++++-- 16 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml new file mode 100644 index 0000000000000..ed34b460d6158 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Assert that the provided Discount is present in the Storefront Shopping Cart. + + + + + + + + diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml index f910a9d47244f..fbfd781505ab7 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml @@ -47,8 +47,10 @@ - - + + + + diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml index d037718a1ec94..fd38120aab98b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml @@ -75,8 +75,10 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml index 88853b2c40d9a..96da616818ae1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml @@ -107,6 +107,8 @@ - + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml index e206633808057..65bb0b4cbfb99 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml @@ -87,8 +87,10 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml index 16af210066997..198ba1cd64f35 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml @@ -80,7 +80,9 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml index 6577ff9440456..70624a4e2e339 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml @@ -84,7 +84,9 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml index da8c8e4bc1f9d..1fe97b1f45036 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -116,6 +116,8 @@ - + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml index f6e736c73db74..c80f43385d166 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -118,6 +118,8 @@ - + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml index 5f110f7074f6f..cd72ec8529816 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml @@ -106,6 +106,8 @@ - + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml index ea96fa41e5cad..3b54df544210f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml @@ -77,8 +77,10 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml index 62c494b988bbd..d0cba156f635e 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml @@ -81,8 +81,10 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml index 70ed09df7a2cc..1a449017e0386 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml @@ -83,7 +83,9 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml index da9ca9055d31b..68f6fc93eab94 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml @@ -77,8 +77,10 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml index ce0d814e50308..0ffe1516d0232 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml @@ -81,7 +81,9 @@ - - + + + + diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml index 1178ca2cfb328..8df45937bb542 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml @@ -117,8 +117,10 @@ - - + + + + From df20ae184f493825627219cadb0e3f0f0e5c6947 Mon Sep 17 00:00:00 2001 From: Aapo Kiiso Date: Tue, 17 Nov 2020 15:12:33 +0200 Subject: [PATCH 013/242] Allow backend login without redirect --- .../Magento/Backend/Controller/Adminhtml/Auth/Login.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php b/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php index 1de77c810f316..18de812b2fa9d 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php @@ -48,12 +48,6 @@ public function execute() return $this->getRedirect($this->_backendUrl->getStartupPageUrl()); } - $requestUrl = $this->getRequest()->getUri(); - $backendUrl = $this->getUrl('*'); - // redirect according to rewrite rule - if ($requestUrl != $backendUrl) { - return $this->getRedirect($backendUrl); - } return $this->resultPageFactory->create(); } From d157d42ebef3a903b39c3a8e224ab0646b91061d Mon Sep 17 00:00:00 2001 From: Anna Pak Date: Mon, 23 Nov 2020 10:41:42 +0200 Subject: [PATCH 014/242] AdminCreateInvoiceTest deprecated --- .../Test/Mftf/Test/AdminCreateInvoiceTest.xml | 96 ++++++++++++------- .../Test/Mftf/Test/AdminInvoiceOrderTest.xml | 65 +++++++++++++ 2 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index 49ae1844a1cf1..3e8fd1e42c12b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -12,54 +12,82 @@ - + <title value="DEPRECATED. Admin should be able to create an invoice"/> <description value="Admin should be able to create an invoice"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-72096"/> <group value="sales"/> + <skip> + <issueID value="DEPRECATED">Use AdminInvoiceOrderTest instead</issueID> + </skip> </annotations> - - <before> + <before> <createData entity="_defaultCategory" stepKey="createCategory"/> - <createData entity="_defaultProduct" stepKey="createSimpleProductApi"> + <createData entity="_defaultProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> - <createData entity="GuestCart" stepKey="createGuestCart"/> - <createData entity="SimpleCartItem" stepKey="addCartItem"> - <requiredEntity createDataKey="createGuestCart"/> - <requiredEntity createDataKey="createSimpleProductApi"/> - </createData> - <createData entity="GuestAddressInformation" stepKey="addGuestOrderAddress"> - <requiredEntity createDataKey="createGuestCart"/> - </createData> - <updateData createDataKey="createGuestCart" entity="GuestOrderPaymentMethod" stepKey="sendGuestPaymentInformation"> - <requiredEntity createDataKey="createGuestCart"/> - </updateData> </before> - <after> - <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> - <deleteData createDataKey="createSimpleProductApi" stepKey="deleteSimpleProductApi"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + <deleteData createDataKey="createCategory" stepKey="deleteProduct1"/> + <deleteData createDataKey="createProduct" stepKey="deleteCategory1"/> </after> - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> - - <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> - <argument name="entity_id" value="$createGuestCart.return$"/> - </actionGroup> - - <actionGroup ref="AdminCreateInvoiceActionGroup" stepKey="createInvoice"/> + <!-- todo: Create an order via the api instead of driving the browser --> + <amOnPage url="{{StorefrontCategoryPage.url($$createCategory.name$$)}}" stepKey="onCategoryPage"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverProduct"/> + <actionGroup ref="StorefrontClickAddToCartButtonActionGroup" stepKey="addToCart"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" time="30" stepKey="waitForProductAdded"/> + <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickCart"/> + <click selector="{{StorefrontMinicartSection.goToCheckout}}" stepKey="goToCheckout"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.email}}" userInput="{{CustomerEntityOne.email}}" stepKey="enterEmail"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.firstName}}" userInput="{{CustomerEntityOne.firstname}}" stepKey="enterFirstName"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.lastName}}" userInput="{{CustomerEntityOne.lastname}}" stepKey="enterLastName"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.street}}" userInput="{{CustomerAddressSimple.street[0]}}" stepKey="enterStreet"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.city}}" userInput="{{CustomerAddressSimple.city}}" stepKey="enterCity"/> + <selectOption selector="{{CheckoutShippingGuestInfoSection.region}}" userInput="{{CustomerAddressSimple.state}}" stepKey="selectRegion"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.postcode}}" userInput="{{CustomerAddressSimple.postcode}}" stepKey="enterPostcode"/> + <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{CustomerAddressSimple.telephone}}" stepKey="enterTelephone"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> + <click selector="{{CheckoutShippingMethodsSection.firstShippingMethod}}" stepKey="selectFirstShippingMethod"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask2"/> + <actionGroup ref="StorefrontCheckoutClickNextButtonActionGroup" stepKey="clickNext"/> + <!-- Checkout select Check/Money Order payment --> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyPayment"/> + <waitForElement selector="{{CheckoutPaymentSection.placeOrder}}" time="30" stepKey="waitForPlaceOrderButton"/> + <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrder"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber}}" stepKey="grabOrderNumber"/> + <!-- end todo --> - <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceGridByOrderId"> - <argument name="orderId" value="$createGuestCart.return$"/> - </actionGroup> - - <actionGroup ref="AdminSelectFirstGridRowActionGroup" stepKey="openInvoiceFromGrid"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> - <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="checkIfOrderStatusIsProcessing"> - <argument name="status" value="Processing"/> - </actionGroup> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="onOrdersPage"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask3"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilter"/> + <fillField selector="{{AdminOrdersGridSection.search}}" userInput="{$grabOrderNumber}" stepKey="searchOrderNum"/> + <click selector="{{AdminOrdersGridSection.submitSearch}}" stepKey="submitSearch"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask4"/> + <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickOrderRow"/> + <actionGroup ref="AdminClickInvoiceButtonOrderViewActionGroup" stepKey="clickInvoice"/> + <actionGroup ref="AdminInvoiceClickSubmitActionGroup" stepKey="clickSubmitInvoice"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeSuccessMessage"/> + <click selector="{{AdminOrderDetailsOrderViewSection.invoices}}" stepKey="clickInvoices"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask5" /> + <see selector="{{AdminOrderDetailsInvoicesSection.content}}" userInput="{$grabOrderNumber}" stepKey="seeInvoice1"/> + <see selector="{{AdminOrderDetailsInvoicesSection.content}}" userInput="John Doe" stepKey="seeInvoice2"/> + <click selector="{{AdminOrderDetailsOrderViewSection.information}}" stepKey="clickInformation"/> + <waitForLoadingMaskToDisappear stepKey="waitForOrderInformationTabLoadingMask"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderStatus"/> + <amOnPage url="{{AdminInvoicesPage.url}}" stepKey="goToInvoices"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask6" /> + <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetGridInitial"/> + <click selector="{{AdminInvoicesGridSection.filter}}" stepKey="clickFilters"/> + <fillField selector="{{AdminInvoicesFiltersSection.orderNum}}" userInput="{$grabOrderNumber}" stepKey="searchOrderNum2"/> + <click selector="{{AdminInvoicesFiltersSection.applyFilters}}" stepKey="clickApplyFilters"/> + <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="clickInvoice2"/> + <see selector="{{AdminInvoiceDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderStatus2"/> </test> -</tests> +</tests> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml new file mode 100644 index 0000000000000..14fe9c1ece95b --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminInvoiceOrderTest"> + <annotations> + <features value="Sales"/> + <stories value="Create an Invoice via the Admin"/> + <title value="Admin should be able to create an invoice"/> + <description value="Admin should be able to create an invoice"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-72096"/> + <group value="sales"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProductApi"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="GuestCart" stepKey="createGuestCart"/> + <createData entity="SimpleCartItem" stepKey="addCartItem"> + <requiredEntity createDataKey="createGuestCart"/> + <requiredEntity createDataKey="createSimpleProductApi"/> + </createData> + <createData entity="GuestAddressInformation" stepKey="addGuestOrderAddress"> + <requiredEntity createDataKey="createGuestCart"/> + </createData> + <updateData createDataKey="createGuestCart" entity="GuestOrderPaymentMethod" stepKey="sendGuestPaymentInformation"> + <requiredEntity createDataKey="createGuestCart"/> + </updateData> + </before> + + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProductApi" stepKey="deleteSimpleProductApi"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> + + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> + + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> + <argument name="entity_id" value="$createGuestCart.return$"/> + </actionGroup> + + <actionGroup ref="AdminCreateInvoiceActionGroup" stepKey="createInvoice"/> + + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceGridByOrderId"> + <argument name="orderId" value="$createGuestCart.return$"/> + </actionGroup> + + <actionGroup ref="AdminSelectFirstGridRowActionGroup" stepKey="openInvoiceFromGrid"/> + + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="checkIfOrderStatusIsProcessing"> + <argument name="status" value="Processing"/> + </actionGroup> + + </test> +</tests> From b23cad2a6a4741d85471c856d2aa8c07e44ba0f6 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 23 Nov 2020 10:48:15 +0200 Subject: [PATCH 015/242] refactored --- .../Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml | 2 +- app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index 3e8fd1e42c12b..1916fb9ebdbbb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -18,7 +18,7 @@ <testCaseId value="MAGETWO-72096"/> <group value="sales"/> <skip> - <issueID value="DEPRECATED">Use AdminInvoiceOrderTest instead</issueID> + <issueId value="DEPRECATED">Use AdminInvoiceOrderTest instead</issueId> </skip> </annotations> <before> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml index 14fe9c1ece95b..3b28fd10d58b9 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml @@ -46,7 +46,7 @@ <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> - <argument name="entity_id" value="$createGuestCart.return$"/> + <argument name="entityId" value="$createGuestCart.return$"/> </actionGroup> <actionGroup ref="AdminCreateInvoiceActionGroup" stepKey="createInvoice"/> From 2d8be9cd0387dc81d2086e9f5f766efc2cd1d813 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 23 Nov 2020 11:26:49 +0200 Subject: [PATCH 016/242] refactored --- .../Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml index 3b28fd10d58b9..922037fe4a3cd 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml @@ -35,6 +35,9 @@ <updateData createDataKey="createGuestCart" entity="GuestOrderPaymentMethod" stepKey="sendGuestPaymentInformation"> <requiredEntity createDataKey="createGuestCart"/> </updateData> + + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> <after> @@ -42,8 +45,6 @@ <deleteData createDataKey="createSimpleProductApi" stepKey="deleteSimpleProductApi"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> - - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> <argument name="entityId" value="$createGuestCart.return$"/> From 97e34547ec7acfadffec4951d4dadd9cae3531f5 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 23 Nov 2020 21:14:35 +0200 Subject: [PATCH 017/242] Refactored AdminMassProductPriceUpdateTest --- ...inCheckProductOnProductGridActionGroup.xml | 22 +++++++++ .../AdminSetPriceForMassUpdateActionGroup.xml | 24 ++++++++++ .../Test/AdminMassProductPriceUpdateTest.xml | 48 ++++++++++++++----- 3 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml new file mode 100644 index 0000000000000..34c9c1edf50cb --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.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="AdminCheckProductOnProductGridActionGroup"> + <annotations> + <description>Check the product on the Product Grid</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + </arguments> + + <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml new file mode 100644 index 0000000000000..b00f181c92360 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.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="AdminSetPriceForMassUpdateActionGroup"> + <annotations> + <description>Click the "Change" checkbox for the "Price" field. Set new price.</description> + </annotations> + <arguments> + <argument name="price" type="string"/> + </arguments> + + <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> + <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> + <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="{{price}}"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index 070c07d9feb7d..b3cf6e357fd6a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -41,19 +41,27 @@ <actionGroup ref="SortProductsByIdDescendingActionGroup" stepKey="sortProductsByIdDescending"/> <!--Select products--> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku($$simpleProduct1.sku$$)}}" stepKey="selectFirstProduct"/> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku($$simpleProduct2.sku$$)}}" stepKey="selectSecondProduct"/> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> + <argument name="product" value="$simpleProduct1$"/> + </actionGroup> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> + <argument name="product" value="$simpleProduct2$"/> + </actionGroup> <!-- Update product price--> - <click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/> - <click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickChangeStatus"/> - <waitForPageLoad stepKey="waitForProductAttributePageToLoad"/> - <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> - <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> - <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="90.99"/> - <click stepKey="clickOnSaveButton" selector="{{AdminEditProductAttributesSection.Save}}"/> - <waitForPageLoad stepKey="waitForUpdatedProductToSave" /> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="Message is added to queue" stepKey="seeAttributeUpateSuccessMsg"/> + <actionGroup ref="AdminClickMassUpdateProductAttributesActionGroup" stepKey="clickDropdown"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> + + <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> + + <actionGroup ref="AdminSaveProductsMassAttributesUpdateActionGroup" stepKey="clickOnSaveButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> <!-- Start message queue --> <actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueueConsumer"> @@ -64,7 +72,21 @@ <magentoCLI command="cron:run --group=index" stepKey="runCron"/> <!--Verify product name, sku and updated price--> - <click stepKey="openFirstProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct1.sku$$)}}"/> + <!-- <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToFirstProductEditPage"> + <argument name="productId" value="$$simpleProduct1.id$$"/> + </actionGroup> --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> + <argument name="product" value="$$simpleProduct1$$"/> + </actionGroup> + + <!-- <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToSecondProductEditPage"> + <argument name="productId" value="$$simpleProduct2.id$$"/> + </actionGroup> --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> + <argument name="product" value="$$simpleProduct2$$"/> + </actionGroup> + + <!-- <click stepKey="openFirstProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct1.sku$$)}}"/> <waitForPageLoad stepKey="waitForFirstProductToLoad"/> <seeInField stepKey="seeFirstProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct1.name$$"/> <seeInField stepKey="seeFirstProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct1.sku$$"/> @@ -75,6 +97,6 @@ <waitForPageLoad stepKey="waitForSecondProductToLoad"/> <seeInField stepKey="seeSecondProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct2.name$$"/> <seeInField stepKey="seeSecondProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct2.sku$$"/> - <seeInField stepKey="seeSecondProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> + <seeInField stepKey="seeSecondProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> --> </test> </tests> From 4c1094ac6a1e2439b5525878f7f273b6dfab45b4 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Wed, 25 Nov 2020 16:02:37 +0200 Subject: [PATCH 018/242] extracted getting column to separate method --- .../Framework/Mview/View/Subscription.php | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index cfab8b2479bc1..6cbfa8012e71b 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -7,8 +7,10 @@ namespace Magento\Framework\Mview\View; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Ddl\Trigger; -use Magento\Framework\Mview\View\StateInterface; +use Magento\Framework\DB\Ddl\TriggerFactory; +use Magento\Framework\Mview\ViewInterface; /** * Mview subscription. @@ -18,17 +20,17 @@ class Subscription implements SubscriptionInterface /** * Database connection * - * @var \Magento\Framework\DB\Adapter\AdapterInterface + * @var AdapterInterface */ protected $connection; /** - * @var \Magento\Framework\DB\Ddl\TriggerFactory + * @var TriggerFactory */ protected $triggerFactory; /** - * @var \Magento\Framework\Mview\View\CollectionInterface + * @var CollectionInterface */ protected $viewCollection; @@ -60,7 +62,7 @@ class Subscription implements SubscriptionInterface * * @var array */ - private $ignoredUpdateColumns = []; + private $ignoredUpdateColumns; /** * @var Resource @@ -69,18 +71,18 @@ class Subscription implements SubscriptionInterface /** * @param ResourceConnection $resource - * @param \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory - * @param \Magento\Framework\Mview\View\CollectionInterface $viewCollection - * @param \Magento\Framework\Mview\ViewInterface $view + * @param TriggerFactory $triggerFactory + * @param CollectionInterface $viewCollection + * @param ViewInterface $view * @param string $tableName * @param string $columnName * @param array $ignoredUpdateColumns */ public function __construct( ResourceConnection $resource, - \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory, - \Magento\Framework\Mview\View\CollectionInterface $viewCollection, - \Magento\Framework\Mview\ViewInterface $view, + TriggerFactory $triggerFactory, + CollectionInterface $viewCollection, + ViewInterface $view, $tableName, $columnName, $ignoredUpdateColumns = [] @@ -96,9 +98,9 @@ public function __construct( } /** - * Create subsciption + * Create subscription * - * @return \Magento\Framework\Mview\View\SubscriptionInterface + * @return SubscriptionInterface */ public function create() { @@ -115,7 +117,7 @@ public function create() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { - /** @var \Magento\Framework\Mview\ViewInterface $view */ + /** @var ViewInterface $view */ $trigger->addStatement($this->buildStatement($event, $view)); } @@ -129,7 +131,7 @@ public function create() /** * Remove subscription * - * @return \Magento\Framework\Mview\View\SubscriptionInterface + * @return SubscriptionInterface */ public function remove() { @@ -144,7 +146,7 @@ public function remove() // Add statements for linked views foreach ($this->getLinkedViews() as $view) { - /** @var \Magento\Framework\Mview\ViewInterface $view */ + /** @var ViewInterface $view */ $trigger->addStatement($this->buildStatement($event, $view)); } @@ -170,13 +172,13 @@ protected function getLinkedViews() $viewList = $this->viewCollection->getViewsByStateMode(StateInterface::MODE_ENABLED); foreach ($viewList as $view) { - /** @var \Magento\Framework\Mview\ViewInterface $view */ + /** @var ViewInterface $view */ // Skip the current view if ($view->getId() == $this->getView()->getId()) { continue; } // Search in view subscriptions - foreach ($view->getSubscriptions() ?? [] as $subscription) { + foreach ($view->getSubscriptions() as $subscription) { if ($subscription['name'] != $this->getTableName()) { continue; } @@ -191,21 +193,12 @@ protected function getLinkedViews() * Build trigger statement for INSERT, UPDATE, DELETE events * * @param string $event - * @param \Magento\Framework\Mview\ViewInterface $view + * @param ViewInterface $view * @return string */ protected function buildStatement($event, $view) { - // Get the subscription for the specific view and specific table. - // We will use column name from it. - $subscriptions = $view->getSubscriptions() ?? []; - if (empty($subscriptions[$this->getTableName()])) { - return ''; - } - - $subscription = $subscriptions[$this->getTableName()]; - - // Get the changelog from View to get changelog column name. + $column = $this->getSubscriptionColumn($view); $changelog = $view->getChangelog(); switch ($event) { @@ -242,14 +235,31 @@ protected function buildStatement($event, $view) default: return ''; } + return sprintf( $trigger, $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())), $this->connection->quoteIdentifier($changelog->getColumnName()), - $this->connection->quoteIdentifier($subscription['column']) + $this->connection->quoteIdentifier($column) ); } + /** + * Returns subscription column name by view + * + * @param ViewInterface $view + * @return string + */ + private function getSubscriptionColumn(ViewInterface $view): string + { + $subscriptions = $view->getSubscriptions(); + if (!isset($subscriptions[$this->getTableName()]['column'])) { + throw new \RuntimeException(sprintf('Column name for view with id "%s" doesn\'t exist', $view->getId())); + } + + return $subscriptions[$this->getTableName()]['column']; + } + /** * Build an "after" event for the given table and event * @@ -269,7 +279,7 @@ private function getAfterEventTriggerName($event) /** * Retrieve View related to subscription * - * @return \Magento\Framework\Mview\ViewInterface + * @return ViewInterface * @codeCoverageIgnore */ public function getView() From 131cd1aae2a397e81457c0daf3962db39d5c0072 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 25 Nov 2020 17:06:44 +0200 Subject: [PATCH 019/242] Refactored AdminMassProductPriceUpdateTest --- ...oductPriceUpdatedOnEditPageActionGroup.xml | 25 +++++++++ .../Test/AdminMassProductPriceUpdateTest.xml | 54 +++++++------------ 2 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml new file mode 100644 index 0000000000000..c7a665119b328 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.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="AssertAdminProductPriceUpdatedOnEditPageActionGroup" extends="OpenEditProductOnBackendActionGroup"> + <annotations> + <description>Validate if Product price is updated on the Product creation/edit page</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + <argument name="price" type="string"/> + </arguments> + + <waitForPageLoad stepKey="waitForProductToLoad"/> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{product.name}}" stepKey="seeProductName"/> + <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{product.sku}}" stepKey="seeProductSku"/> + <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{price}}" stepKey="seeProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index b3cf6e357fd6a..42719e2d6aa12 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -25,22 +25,16 @@ </before> <after> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> - <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <!--Open Product Index Page--> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndex"/> - <!--Search products using keyword --> - <actionGroup ref="SearchProductGridByKeyword2ActionGroup" stepKey="searchByKeyword"> - <argument name="keyword" value="Testp"/> - </actionGroup> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="searchByKeyword"/> - <!--Sort Products by ID in descending order--> <actionGroup ref="SortProductsByIdDescendingActionGroup" stepKey="sortProductsByIdDescending"/> - <!--Select products--> <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> <argument name="product" value="$simpleProduct1$"/> </actionGroup> @@ -48,7 +42,6 @@ <argument name="product" value="$simpleProduct2$"/> </actionGroup> - <!-- Update product price--> <actionGroup ref="AdminClickMassUpdateProductAttributesActionGroup" stepKey="clickDropdown"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> @@ -63,40 +56,33 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> - <!-- Start message queue --> <actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueueConsumer"> <argument name="consumerName" value="{{AdminProductAttributeUpdateConsumerData.consumerName}}"/> <argument name="maxMessages" value="{{AdminProductAttributeUpdateConsumerData.messageLimit}}"/> </actionGroup> - <!-- Run cron --> + <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <!--Verify product name, sku and updated price--> - <!-- <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToFirstProductEditPage"> - <argument name="productId" value="$$simpleProduct1.id$$"/> - </actionGroup> --> - <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> + <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> <argument name="product" value="$$simpleProduct1$$"/> + <argument name="price" value="90.99"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> - <!-- <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToSecondProductEditPage"> - <argument name="productId" value="$$simpleProduct2.id$$"/> - </actionGroup> --> - <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="waitForProductsToLoad"/> + + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> + <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> <argument name="product" value="$$simpleProduct2$$"/> - </actionGroup> - - <!-- <click stepKey="openFirstProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct1.sku$$)}}"/> - <waitForPageLoad stepKey="waitForFirstProductToLoad"/> - <seeInField stepKey="seeFirstProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct1.name$$"/> - <seeInField stepKey="seeFirstProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct1.sku$$"/> - <seeInField stepKey="seeFirstProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> - <click stepKey="clickOnBackButton" selector="{{AdminGridMainControls.back}}"/> - <waitForPageLoad stepKey="waitForProductsToLoad"/> - <click stepKey="openSecondProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct2.sku$$)}}"/> - <waitForPageLoad stepKey="waitForSecondProductToLoad"/> - <seeInField stepKey="seeSecondProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct2.name$$"/> - <seeInField stepKey="seeSecondProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct2.sku$$"/> - <seeInField stepKey="seeSecondProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> --> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> + </test> </tests> From bdb653dc3ff44f1ce1486935e27873620ea3f3bd Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 25 Nov 2020 17:14:32 +0200 Subject: [PATCH 020/242] delete unneeded file Please enter the commit message for your changes. Lines starting --- ...inCheckProductOnProductGridActionGroup.xml | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml deleted file mode 100644 index 34c9c1edf50cb..0000000000000 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?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="AdminCheckProductOnProductGridActionGroup"> - <annotations> - <description>Check the product on the Product Grid</description> - </annotations> - <arguments> - <argument name="product" type="entity"/> - </arguments> - - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> - - </actionGroup> -</actionGroups> From faf0c872ac4e03555a278009f12743c0ef0b8412 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 25 Nov 2020 17:22:58 +0200 Subject: [PATCH 021/242] revert deletion --- ...inCheckProductOnProductGridActionGroup.xml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml new file mode 100644 index 0000000000000..3bd68e80810e6 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.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="AdminCheckProductOnProductGridActionGroup"> + <annotations> + <description>Check the product on the Product Grid</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + </arguments> + + <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> + + </actionGroup> +</actionGroups> \ No newline at end of file From dd4334df1a3c28e4ee1c84e782971d77c15622d6 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 25 Nov 2020 17:29:51 +0200 Subject: [PATCH 022/242] extended decription fo Action Group Please enter the commit message for your changes. Lines starting --- .../ActionGroup/AdminCheckProductOnProductGridActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index 3bd68e80810e6..aebd595a919f8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCheckProductOnProductGridActionGroup"> <annotations> - <description>Check the product on the Product Grid</description> + <description>Check the checkbox for the product on the Product Grid</description> </annotations> <arguments> <argument name="product" type="entity"/> From 4ad7aae8b66c9b18a6c67c53d202014f1086b4f5 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Mon, 30 Nov 2020 10:37:48 +0200 Subject: [PATCH 023/242] fix unit test --- .../Mview/Test/Unit/View/SubscriptionTest.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php index c4df73a79a5d8..df7d246f538aa 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php @@ -383,6 +383,18 @@ public function testBuildStatementIgnoredColumnSubscriptionLevel(): void ->method('getViewId') ->willReturn($viewId); + $this->viewMock->expects($this->once()) + ->method('getSubscriptions') + ->willReturn( + [ + $this->tableName => ['name' => $this->tableName, 'column' => 'columnName'], + 'cataloginventory_stock_item' => ['name' => 'otherTableName', 'column' => 'columnName'] + ] + ); + $this->viewMock->expects($this->once()) + ->method('getChangeLog') + ->willReturn($otherChangelogMock); + $model = new Subscription( $this->resourceMock, $this->triggerFactoryMock, @@ -396,7 +408,7 @@ public function testBuildStatementIgnoredColumnSubscriptionLevel(): void $method = new \ReflectionMethod($model, 'buildStatement'); $method->setAccessible(true); - $statement = $method->invoke($model, Trigger::EVENT_UPDATE, $otherChangelogMock); + $statement = $method->invoke($model, Trigger::EVENT_UPDATE, $this->viewMock); $this->assertStringNotContainsString($ignoredColumnName, $statement); $this->assertStringContainsString($notIgnoredColumnName, $statement); From 8a9b7689bb75567ae92e7e9b938f9095475fae3e Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Mon, 30 Nov 2020 10:41:31 +0200 Subject: [PATCH 024/242] define arguments & return types --- lib/internal/Magento/Framework/Mview/View/Subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index 20ea0998afc2d..d8367bb832e82 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -205,7 +205,7 @@ protected function getLinkedViews() * @param ViewInterface $view * @return string */ - protected function buildStatement($event, $view) + protected function buildStatement(string $event, ViewInterface $view): string { $column = $this->getSubscriptionColumn($view); $changelog = $view->getChangelog(); From 758b0d64067f7e3091b0a4a550b0a2a79e79322e Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 30 Nov 2020 11:01:33 +0200 Subject: [PATCH 025/242] refactoring --- .../ActionGroup/AdminCheckProductOnProductGridActionGroup.xml | 2 +- .../Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index aebd595a919f8..2faeea1cc299b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -19,4 +19,4 @@ <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index 42719e2d6aa12..63277e2ed88fd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -25,7 +25,7 @@ </before> <after> <deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/> - <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> From ce7a3517b4d08ecd4b07eefcbf7e791e4f94db6b Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 30 Nov 2020 17:06:52 +0200 Subject: [PATCH 026/242] refactored --- .../Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index 1916fb9ebdbbb..c2070043e63de 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml @@ -90,4 +90,4 @@ <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="clickInvoice2"/> <see selector="{{AdminInvoiceDetailsInformationSection.orderStatus}}" userInput="Processing" stepKey="seeOrderStatus2"/> </test> -</tests> \ No newline at end of file +</tests> From 52e5d2cb33ddf9412e9fda9ef0694013f9796938 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 2 Dec 2020 17:19:59 +0200 Subject: [PATCH 027/242] autoformatted --- ...inCheckProductOnProductGridActionGroup.xml | 25 ++++---- .../AdminSetPriceForMassUpdateActionGroup.xml | 7 +-- ...oductPriceUpdatedOnEditPageActionGroup.xml | 5 +- .../Test/AdminMassProductPriceUpdateTest.xml | 57 +++++++++---------- 4 files changed, 45 insertions(+), 49 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index 2faeea1cc299b..4216f4eedfda6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8"?> <!-- /** * Copyright © Magento, Inc. All rights reserved. @@ -6,17 +6,16 @@ */ --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCheckProductOnProductGridActionGroup"> - <annotations> - <description>Check the checkbox for the product on the Product Grid</description> - </annotations> - <arguments> - <argument name="product" type="entity"/> - </arguments> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCheckProductOnProductGridActionGroup"> + <annotations> + <description>Check the checkbox for the product on the Product Grid</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + </arguments> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> + <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> - </actionGroup> -</actionGroups> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml index b00f181c92360..0bae2a2f627a5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml @@ -6,8 +6,7 @@ */ --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminSetPriceForMassUpdateActionGroup"> <annotations> <description>Click the "Change" checkbox for the "Price" field. Set new price.</description> @@ -16,9 +15,9 @@ <argument name="price" type="string"/> </arguments> - <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> + <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="{{price}}"/> </actionGroup> -</actionGroups> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml index c7a665119b328..42577f5e7735d 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml @@ -6,8 +6,7 @@ */ --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertAdminProductPriceUpdatedOnEditPageActionGroup" extends="OpenEditProductOnBackendActionGroup"> <annotations> <description>Validate if Product price is updated on the Product creation/edit page</description> @@ -22,4 +21,4 @@ <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{product.sku}}" stepKey="seeProductSku"/> <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{price}}" stepKey="seeProductPrice"/> </actionGroup> -</actionGroups> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index 63277e2ed88fd..f76ff23a3ec97 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -6,8 +6,7 @@ */ --> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminMassProductPriceUpdateTest"> <annotations> <stories value="Mass product update"/> @@ -36,25 +35,25 @@ <actionGroup ref="SortProductsByIdDescendingActionGroup" stepKey="sortProductsByIdDescending"/> <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> - <argument name="product" value="$simpleProduct1$"/> + <argument name="product" value="$simpleProduct1$"/> </actionGroup> - <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> - <argument name="product" value="$simpleProduct2$"/> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> + <argument name="product" value="$simpleProduct2$"/> </actionGroup> <actionGroup ref="AdminClickMassUpdateProductAttributesActionGroup" stepKey="clickDropdown"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> - <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> - <argument name="price" value="90.99"/> - </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> + <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> <actionGroup ref="AdminSaveProductsMassAttributesUpdateActionGroup" stepKey="clickOnSaveButton"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> <actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueueConsumer"> <argument name="consumerName" value="{{AdminProductAttributeUpdateConsumerData.consumerName}}"/> @@ -63,26 +62,26 @@ <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> - <argument name="product" value="$$simpleProduct1$$"/> - <argument name="price" value="90.99"/> + <argument name="product" value="$$simpleProduct1$$"/> + <argument name="price" value="90.99"/> </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="waitForProductsToLoad"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> - <argument name="product" value="$$simpleProduct2$$"/> - <argument name="price" value="90.99"/> - </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> + <argument name="product" value="$$simpleProduct2$$"/> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> </test> -</tests> +</tests> \ No newline at end of file From a048fb7c242556759d8d15081340906b48ed26ab Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 2 Dec 2020 17:30:29 +0200 Subject: [PATCH 028/242] corrected spacing --- .../AdminSetPriceForMassUpdateActionGroup.xml | 7 ++- ...oductPriceUpdatedOnEditPageActionGroup.xml | 5 +- .../Test/AdminMassProductPriceUpdateTest.xml | 57 ++++++++++--------- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml index 0bae2a2f627a5..b00f181c92360 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml @@ -6,7 +6,8 @@ */ --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminSetPriceForMassUpdateActionGroup"> <annotations> <description>Click the "Change" checkbox for the "Price" field. Set new price.</description> @@ -15,9 +16,9 @@ <argument name="price" type="string"/> </arguments> - <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> + <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="{{price}}"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml index 42577f5e7735d..c7a665119b328 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml @@ -6,7 +6,8 @@ */ --> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AssertAdminProductPriceUpdatedOnEditPageActionGroup" extends="OpenEditProductOnBackendActionGroup"> <annotations> <description>Validate if Product price is updated on the Product creation/edit page</description> @@ -21,4 +22,4 @@ <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{product.sku}}" stepKey="seeProductSku"/> <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{price}}" stepKey="seeProductPrice"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index f76ff23a3ec97..63277e2ed88fd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -6,7 +6,8 @@ */ --> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminMassProductPriceUpdateTest"> <annotations> <stories value="Mass product update"/> @@ -35,25 +36,25 @@ <actionGroup ref="SortProductsByIdDescendingActionGroup" stepKey="sortProductsByIdDescending"/> <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> - <argument name="product" value="$simpleProduct1$"/> + <argument name="product" value="$simpleProduct1$"/> </actionGroup> - <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> - <argument name="product" value="$simpleProduct2$"/> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> + <argument name="product" value="$simpleProduct2$"/> </actionGroup> <actionGroup ref="AdminClickMassUpdateProductAttributesActionGroup" stepKey="clickDropdown"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> - <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> - <argument name="price" value="90.99"/> - </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> + <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> <actionGroup ref="AdminSaveProductsMassAttributesUpdateActionGroup" stepKey="clickOnSaveButton"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> <actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueueConsumer"> <argument name="consumerName" value="{{AdminProductAttributeUpdateConsumerData.consumerName}}"/> @@ -62,26 +63,26 @@ <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> - <argument name="product" value="$$simpleProduct1$$"/> - <argument name="price" value="90.99"/> + <argument name="product" value="$$simpleProduct1$$"/> + <argument name="price" value="90.99"/> </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="waitForProductsToLoad"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> - <argument name="product" value="$$simpleProduct2$$"/> - <argument name="price" value="90.99"/> - </actionGroup> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> + <argument name="product" value="$$simpleProduct2$$"/> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> </test> -</tests> \ No newline at end of file +</tests> From 6fc419105aa467bc909305775e8398d151969f0f Mon Sep 17 00:00:00 2001 From: Anna Pak <58164147+AnnaAPak@users.noreply.github.com> Date: Fri, 4 Dec 2020 09:33:05 +0200 Subject: [PATCH 029/242] Added line --- .../ActionGroup/AdminCheckProductOnProductGridActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index 4216f4eedfda6..627659062b133 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -18,4 +18,4 @@ <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> From 64b617f95788ea499ced46dd620bf70a07868478 Mon Sep 17 00:00:00 2001 From: Anna Pak <58164147+AnnaAPak@users.noreply.github.com> Date: Fri, 4 Dec 2020 09:34:35 +0200 Subject: [PATCH 030/242] Added space --- .../Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index 63277e2ed88fd..8a5da6d6e3640 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -38,7 +38,7 @@ <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> <argument name="product" value="$simpleProduct1$"/> </actionGroup> - <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> <argument name="product" value="$simpleProduct2$"/> </actionGroup> From 9691ef605f9f46e4ee0d4b478dc0d1f736f1d125 Mon Sep 17 00:00:00 2001 From: Anna Pak <58164147+AnnaAPak@users.noreply.github.com> Date: Fri, 4 Dec 2020 09:43:49 +0200 Subject: [PATCH 031/242] corrected spacing --- .../ActionGroup/AdminCheckProductOnProductGridActionGroup.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index 627659062b133..0e98db3e5d8a8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -9,10 +9,10 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminCheckProductOnProductGridActionGroup"> <annotations> - <description>Check the checkbox for the product on the Product Grid</description> + <description>Check the checkbox for the product on the Product Grid</description> </annotations> <arguments> - <argument name="product" type="entity"/> + <argument name="product" type="entity"/> </arguments> <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> From 2f10855d003758de54fb23c83a972de25b6a26a7 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Fri, 4 Dec 2020 10:40:19 +0200 Subject: [PATCH 032/242] Allow to load base64 encoded images and fonts --- app/code/Magento/Csp/etc/config.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/code/Magento/Csp/etc/config.xml b/app/code/Magento/Csp/etc/config.xml index 6e2235479da93..07761995fdbca 100644 --- a/app/code/Magento/Csp/etc/config.xml +++ b/app/code/Magento/Csp/etc/config.xml @@ -92,6 +92,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </images> <frames> <policy_id>frame-src</policy_id> @@ -120,6 +123,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </fonts> </storefront> <admin> @@ -197,6 +203,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </images> <frames> <policy_id>frame-src</policy_id> @@ -225,6 +234,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </fonts> </admin> </policies> From 41c3aa20144741faa1a5935c1764416872166474 Mon Sep 17 00:00:00 2001 From: Renon Stewart <srenon@users.noreply.github.com> Date: Tue, 8 Dec 2020 01:16:25 -0500 Subject: [PATCH 033/242] Issues 31197 - Loading wrong order tax info --- app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php index e923b006a0ac6..1f8d0a0bc265d 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php @@ -95,7 +95,7 @@ public function getFullTaxInfo() $taxClassAmount = $this->_taxHelper->getCalculatedTaxes($source); if (empty($taxClassAmount)) { - $rates = $this->_taxOrderFactory->create()->getCollection()->loadByOrder($source)->toArray(); + $rates = $this->_taxOrderFactory->create()->getCollection()->loadByOrder($this->getOrder())->toArray(); $taxClassAmount = $this->_taxCalculation->reproduceProcess($rates['items']); } From 1de30e394110c0fb284994c4da73390530462723 Mon Sep 17 00:00:00 2001 From: saphaljha <saphal.jha@krishtechnolabs.com> Date: Tue, 8 Dec 2020 19:10:15 +0530 Subject: [PATCH 034/242] Changed config to store before default --- app/code/Magento/Newsletter/Model/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Newsletter/Model/Config.php b/app/code/Magento/Newsletter/Model/Config.php index c469d35e74f72..eba0980e993b2 100644 --- a/app/code/Magento/Newsletter/Model/Config.php +++ b/app/code/Magento/Newsletter/Model/Config.php @@ -41,7 +41,7 @@ public function __construct( * @param string $scopeType * @return bool */ - public function isActive(string $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT): bool + public function isActive(string $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_STORE): bool { return $this->scopeConfig->isSetFlag(self::XML_PATH_NEWSLETTER_ACTIVE, $scopeType); } From 760a4e362ec11ffaec8e317c16fbea9e5557de45 Mon Sep 17 00:00:00 2001 From: Aapo Kiiso <aapo@lamia.fi> Date: Wed, 9 Dec 2020 08:53:52 +0200 Subject: [PATCH 035/242] Fix test to check that login form is visible after admin expiration --- .../Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml index dc88ad9d2cbf1..4996992c70245 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml @@ -48,7 +48,7 @@ <wait time="120" stepKey="waitForUserToExpire"/> <actionGroup ref="AdminOpenCustomersGridActionGroup" stepKey="navigateToCustomers"/> <!-- Confirm that user is logged out --> - <seeInCurrentUrl url="{{AdminLoginPage.url}}" stepKey="seeAdminLoginUrl"/> + <seeElement selector="{{AdminLoginFormSection.loginBlock}}" stepKey="assertAdminLoginPageIsAvailable"/> <!-- Delete created user --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> From edab7db4816e971a8cdf43c8704f97765e12b49d Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 10 Dec 2020 09:57:32 +0200 Subject: [PATCH 036/242] Refactored Search Actions --- ...tNameIsNotOnProductMainPageActionGroup.xml | 21 +++++++++++++ ...ateProductAttributeFromProductPageTest.xml | 14 ++++++--- ...CustomOptionsSuiteAndImportOptionsTest.xml | 14 ++++++--- ...nCreateVirtualProductWithTierPriceTest.xml | 15 ++++++--- ...rifyDataOverridingOnStoreViewLevelTest.xml | 31 +++++++++++++------ ...rifyDataOverridingOnStoreViewLevelTest.xml | 20 +++++++----- ...dminUpdateSimpleProductTieredPriceTest.xml | 16 +++++++--- ...RegularPriceInStockDisabledProductTest.xml | 14 ++++++--- ...WithRegularPriceInStockEnabledFlatTest.xml | 7 +++-- ...PriceInStockNotVisibleIndividuallyTest.xml | 19 +++++++----- ...ceInStockVisibleInCatalogAndSearchTest.xml | 18 +++++++---- ...arPriceInStockVisibleInCatalogOnlyTest.xml | 27 ++++++++++------ ...larPriceInStockVisibleInSearchOnlyTest.xml | 15 ++++++--- ...eProductWithRegularPriceOutOfStockTest.xml | 15 ++++++--- ...rPriceInStockVisibleInCategoryOnlyTest.xml | 14 ++++++--- ...iceOutOfStockVisibleInCategoryOnlyTest.xml | 14 ++++++--- ...PriceOutOfStockVisibleInSearchOnlyTest.xml | 14 ++++++--- ...eInStockVisibleInCategoryAndSearchTest.xml | 14 ++++++--- ...tOfStockVisibleInCategoryAndSearchTest.xml | 15 ++++++--- ...rPriceInStockVisibleInCategoryOnlyTest.xml | 14 ++++++--- ...tOfStockVisibleInCategoryAndSearchTest.xml | 15 ++++++--- ...MinimalQueryLengthForCatalogSearchTest.xml | 14 ++++++--- 22 files changed, 243 insertions(+), 117 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml new file mode 100644 index 0000000000000..9492aabe1c6f3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.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="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup"> + <annotations> + <description>Validates that the provided Product Name is NOT present on a Storefront page.</description> + </annotations> + <arguments> + <argument name="productName" type="string"/> + </arguments> + + <waitForPageLoad stepKey="waitForTheProductPageToLoad"/> + <dontSee selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{productName}}" stepKey="dontSeeProductName"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml index 61ef389c7909e..759087afbf95a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml @@ -129,10 +129,14 @@ <!--Verify Product Attribute present in search page --> <amOnPage url="$$createCategory.name$$.html" stepKey="goToStorefrontPage1"/> <waitForPageLoad stepKey="waitForProductFrontPageToLoad1"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{ProductAttributeOption8.value}}" stepKey="fillAttribute"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{SimpleProduct.name}}" stepKey="seeProductNameInCategoryPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <argument name="phrase" value="{{ProductAttributeOption8.value}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchResultToLoad"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductNameInCategoryPage"> + <argument name="productName" value="{{SimpleProduct.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml index 7871f4305575a..1874f0709d9ec 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithCustomOptionsSuiteAndImportOptionsTest.xml @@ -127,11 +127,15 @@ <!-- Verify customer see created virtual product with custom options suite and import options(from above step) on storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(virtualProductCustomImportOptions.urlKey)}}" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{virtualProductCustomImportOptions.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{virtualProductCustomImportOptions.name}}" stepKey="seeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{virtualProductCustomImportOptions.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeVirtualProductName"> + <argument name="productName" value="{{virtualProductCustomImportOptions.name}}"/> + </actionGroup> <click selector="{{StorefrontQuickSearchResultsSection.productLink}}" stepKey="openSearchedProduct"/> <!-- Verify we see created virtual product with custom options suite and import options on the storefront page --> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml index 994ea76ca33df..0c488b86a92c8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateVirtualProductWithTierPriceTest.xml @@ -105,11 +105,16 @@ <!-- Verify customer see created virtual product with tier price(from above step) on storefront page and is searchable by sku --> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomePage"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{virtualProductBigQty.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{virtualProductBigQty.name}}" stepKey="seeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{virtualProductBigQty.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeVirtualProductName"> + <argument name="productName" value="{{virtualProductBigQty.name}}"/> + </actionGroup> + <grabTextFrom selector="{{StorefrontQuickSearchResultsSection.asLowAsLabel}}" stepKey="tierPriceTextOnStorefrontPage"/> <assertEquals stepKey="assertTierPriceTextOnCategoryPage"> <expectedResult type="string">As low as ${{tierPriceOnVirtualProduct.price}}</expectedResult> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml index 5f7cecfde188a..3b1e9582ebc4c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductNameToVerifyDataOverridingOnStoreViewLevelTest.xml @@ -71,20 +71,31 @@ <!--Verify customer see default simple product name on magento storefront page --> <amOnPage url="{{StorefrontProductPage.url($$initialSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="$$initialSimpleProduct.sku$$" stepKey="fillDefaultSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="$$initialSimpleProduct.name$$" stepKey="seeDefaultProductName"/> + + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillDefaultSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="$$initialSimpleProduct.sku$$"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeDefaultProductName"> + <argument name="productName" value="$$initialSimpleProduct.name$$"/> + </actionGroup> <!--Verify customer see simple product with updated name on magento storefront page under store view section --> <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="clickStoreViewSwitcher"/> <waitForPageLoad stepKey="waitForStoreSwitcherLoad"/> <click selector="{{StorefrontHeaderSection.storeView(customStoreFR.name)}}" stepKey="clickStoreViewOption"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="$$initialSimpleProduct.sku$$" stepKey="fillDefaultSimpleProductSkuInSearch"/> - <waitForPageLoad stepKey="waitForSearchTextBoxLoad"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextButton"/> - <waitForPageLoad stepKey="waitForTextSearchLoad"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductDataOverriding.name}}" stepKey="seeUpdatedSimpleProductName"/> + + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillDefaultSimpleProductSkuInSearch"> + <argument name="phrase" value="$$initialSimpleProduct.sku$$"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBoxLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForTextSearchLoad"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeUpdatedSimpleProductName"> + <argument name="productName" value="{{simpleProductDataOverriding.name}}"/> + </actionGroup> + </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml index 8a05ed9d64b8b..62ca93f9bba7b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductPriceToVerifyDataOverridingOnStoreViewLevelTest.xml @@ -69,20 +69,24 @@ <!-- Verify customer see simple product with updated price on magento storefront page --> <amOnPage url="{{StorefrontProductPage.url($$initialSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="$$initialSimpleProduct.sku$$" stepKey="fillDefaultSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillDefaultSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="$$initialSimpleProduct.sku$$"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> <see selector="{{StorefrontQuickSearchResultsSection.regularPrice}}" userInput="{{simpleProductDataOverriding.price}}" stepKey="seeUpdatedProductPriceOnStorefrontPage"/> <!-- Verify customer see simple product with updated price on magento storefront page under store view section --> <click selector="{{StorefrontHeaderSection.storeViewSwitcher}}" stepKey="clickStoreViewSwitcher"/> <waitForPageLoad stepKey="waitForStoreSwitcherLoad"/> <click selector="{{StorefrontHeaderSection.storeView(customStoreFR.name)}}" stepKey="clickStoreViewOption"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="$$initialSimpleProduct.sku$$" stepKey="fillDefaultSimpleProductSkuInSearch"/> - <waitForPageLoad stepKey="waitForSearchTextBoxLoad"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextButton"/> - <waitForPageLoad stepKey="waitForTextSearchLoad"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillDefaultSimpleProductSkuInSearch"> + <argument name="phrase" value="$$initialSimpleProduct.sku$$"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBoxLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForTextSearchLoad"/> <see selector="{{StorefrontQuickSearchResultsSection.regularPrice}}" userInput="{{simpleProductDataOverriding.price}}" stepKey="seeUpdatedProductPriceOnStorefrontPageUnderStoreViewSection"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index 300b312612253..d7c5377327193 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -112,6 +112,7 @@ <seeInField selector="{{AdminProductFormSection.productWeightSelect}}" userInput="{{simpleProductTierPrice300InStock.weightSelect}}" stepKey="seeSimpleProductWeightSelect"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="seeSelectedCategories"/> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelectToApplyChanges"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductTierPrice300InStock.urlKey}}" stepKey="seeUrlKey"/> @@ -143,10 +144,15 @@ <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductTierPrice300InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductTierPrice300InStock.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductTierPrice300InStock.name}}" stepKey="seeProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="{{simpleProductTierPrice300InStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="{{simpleProductTierPrice300InStock.name}}"/> + </actionGroup> + </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml index a9630aba467c6..2775876895499 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml @@ -81,10 +81,14 @@ <!--Verify customer don't see updated simple product link on magento storefront page --> <amOnPage url="{{StorefrontProductPage.url(simpleProductDisabled.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductDisabled.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductDisabled.name}}" stepKey="dontSeeProductNameOnStorefrontPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="{{simpleProductDisabled.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductNameOnStorefrontPage"> + <argument name="productName" value="{{simpleProductDisabled.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml index aa1b1ae702914..c1b80b94179fa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.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="AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest"> + <test name="AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest" deprecated="Use AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatCatalogTest instead"> <annotations> <stories value="Update Simple Product"/> - <title value="Update Simple Product with Regular Price (In Stock) Enabled Flat"/> + <title value="DEPRECACTED. Update Simple Product with Regular Price (In Stock) Enabled Flat"/> <description value="Test log in to Update Simple Product and Update Simple Product with Regular Price (In Stock) Enabled Flat"/> <testCaseId value="MC-10818"/> <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> + <skip> + <issueId value="DEPRECATED">Use AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatCatalogTest instead</issueId> + </skip> </annotations> <before> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index 86fac835ce44d..7f347a6280d91 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -57,7 +57,7 @@ <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductNotVisibleIndividually.visibility}}" stepKey="selectVisibility"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductNotVisibleIndividually.urlKey}}" stepKey="fillSimpleProductUrlKey"/> @@ -86,18 +86,23 @@ <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductNotVisibleIndividually.weightNoDecimals}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="seeSelectedCategories" /> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductNotVisibleIndividually.visibility}}" stepKey="seeSimpleProductVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSectionHeader"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductNotVisibleIndividually.urlKey}}" stepKey="seeSimpleProductUrlKey"/> <!--Verify customer don't see updated simple product link on magento storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductNotVisibleIndividually.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> + <amOnPage url="{{StorefrontProductPage.url(simpleProductNotVisibleIndividually.urlKey)}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductNotVisibleIndividually.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductNotVisibleIndividually.name}}" stepKey="dontSeeSimpleProductNameOnMagentoStorefrontPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <argument name="phrase" value="{{simpleProductNotVisibleIndividually.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeSimpleProductNameOnMagentoStorefrontPage"> + <argument name="productName" value="{{simpleProductNotVisibleIndividually.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 320edba5feeff..0158633d77df3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -86,6 +86,7 @@ <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice245InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice245InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -121,12 +122,17 @@ </assertEquals> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> + <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductRegularPrice245InStock.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductRegularPrice245InStock.name}}" stepKey="seeSimpleProductNameOnStorefrontPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <argument name="phrase" value="{{simpleProductRegularPrice245InStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeSimpleProductNameOnStorefrontPage"> + <argument name="productName" value="{{simpleProductRegularPrice245InStock.name}}"/> + </actionGroup> + </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 77c3e7548a3cf..5b45c4dce8e5b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -40,8 +40,10 @@ <actionGroup ref="FilterProductGridBySku2ActionGroup" stepKey="filterProductGrid"> <argument name="sku" value="$$initialSimpleProduct.sku$$"/> </actionGroup> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> - <waitForPageLoad stepKey="waitUntilProductIsOpened"/> + <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilProductIsOpened"/> + <!-- <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> + <waitForPageLoad stepKey="waitUntilProductIsOpened"/> --> <!-- Update simple product with regular price(in stock) --> <fillField selector="{{AdminProductFormSection.productName}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="fillSimpleProductName"/> @@ -74,8 +76,10 @@ <fillField selector="{{AdminProductGridFilterSection.nameFilter}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="fillSimpleProductNameInNameFilter"/> <fillField selector="{{AdminProductGridFilterSection.skuFilter}}" userInput="{{simpleProductRegularPrice32501InStock.sku}}" stepKey="fillProductSku"/> <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> - <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyUpdatedSimpleProductVisibleInGrid"/> - <waitForPageLoad stepKey="waitUntilSimpleProductPageIsOpened"/> + <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickFirstRowToVerifyUpdatedSimpleProductVisibleInGrid"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilSimpleProductPageIsOpened"/> + <!-- <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyUpdatedSimpleProductVisibleInGrid"/> + <waitForPageLoad stepKey="waitUntilSimpleProductPageIsOpened"/> --> <!-- Verify customer see updated simple product in the product form page --> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="seeSimpleProductName"/> @@ -86,6 +90,7 @@ <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32501InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice32501InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -123,10 +128,14 @@ <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32501InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductRegularPrice32501InStock.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="dontSeeProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBo"> + <argument name="phrase" value="{{simpleProductRegularPrice32501InStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> + <argument name="productName" value="{{simpleProductRegularPrice32501InStock.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index 39dab0b08915c..7b6db040ad8e1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -86,6 +86,7 @@ <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice325InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice325InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -118,10 +119,14 @@ <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice325InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductRegularPrice325InStock.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductRegularPrice325InStock.name}}" stepKey="seeProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="{{simpleProductRegularPrice325InStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductName"> + <argument name="productName" value="{{simpleProductRegularPrice325InStock.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 441bc9b8f8005..8caf2afb1b914 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -86,6 +86,7 @@ <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32503OutOfStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32503OutOfStock.urlKey}}" stepKey="seeUrlKey"/> @@ -117,10 +118,14 @@ <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32503OutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{simpleProductRegularPrice32503OutOfStock.sku}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductRegularPrice32503OutOfStock.name}}" stepKey="dontSeeProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> + <argument name="phrase" value="{{simpleProductRegularPrice32503OutOfStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> + <argument name="productName" value="{{simpleProductRegularPrice32503OutOfStock.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml index f4375ad499dfd..469446cd702ce 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml @@ -116,11 +116,15 @@ <!-- Verify customer don't see updated virtual product link on storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductRegularPrice.urlKey)}}" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductRegularPrice.sku}}" stepKey="fillVirtualProductSkuOnStorefrontPage"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductRegularPrice.name}}" stepKey="dontSeeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductSkuOnStorefrontPagee"> + <argument name="phrase" value="{{updateVirtualProductRegularPrice.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <argument name="productName" value="{{updateVirtualProductRegularPrice.name}}"/> + </actionGroup> <!-- Verify customer see updated virtual product in category page --> <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml index 343326547254a..ac8b80045bdc0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml @@ -122,10 +122,14 @@ <!--Verify customer don't see updated virtual product link(from above step) on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductRegularPrice5OutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductRegularPrice5OutOfStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductRegularPrice5OutOfStock.name}}" stepKey="dontSeeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualProductRegularPrice5OutOfStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <argument name="productName" value="{{updateVirtualProductRegularPrice5OutOfStock.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml index 0d6a1c87c62fe..942079421e3aa 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml @@ -100,11 +100,15 @@ <!--Verify customer don't see updated virtual product link on magento storefront page --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductRegularPrice99OutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductRegularPrice99OutOfStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductRegularPrice99OutOfStock.name}}" stepKey="dontSeeVirtualProductLinkOnStorefrontPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualProductRegularPrice99OutOfStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductLinkOnStorefrontPage"> + <argument name="productName" value="{{updateVirtualProductRegularPrice99OutOfStock.name}}"/> + </actionGroup> <!--Verify customer don't see updated virtual product link on category page --> <amOnPage url="{{StorefrontCategoryPage.url($$initialCategoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml index f423cd6c77807..da43d12ab7983 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceInStockVisibleInCategoryAndSearchTest.xml @@ -112,11 +112,15 @@ <!-- Verify customer see updated virtual product on the magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductSpecialPrice.urlKey)}}" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductSpecialPrice.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductSpecialPrice.name}}" stepKey="seeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualProductSpecialPrice.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeVirtualProductName"> + <argument name="productName" value="{{updateVirtualProductSpecialPrice.name}}"/> + </actionGroup> <!--Verify customer see updated virtual product with special price(from above step) on product storefront page by url key --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductSpecialPrice.urlKey)}}" stepKey="goToProductStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml index 78a15ee7eb195..c72fe4e8d8535 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -130,10 +130,15 @@ <!--Verify customer don't see updated virtual product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductSpecialPriceOutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualProductSpecialPriceOutOfStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductSpecialPriceOutOfStock.name}}" stepKey="dontSeeVirtualProductNameOnStorefrontPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualProductSpecialPriceOutOfStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductNameOnStorefrontPage"> + <argument name="productName" value="{{updateVirtualProductSpecialPriceOutOfStock.name}}"/> + </actionGroup> + </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml index f64e628c0edb9..1006ba0df12db 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml @@ -146,10 +146,14 @@ <!--Verify customer don't see updated virtual product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductWithTierPriceInStock.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"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualProductWithTierPriceInStock.name}}" stepKey="dontSeeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualProductTierPriceInStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <argument name="productName" value="{{updateVirtualProductWithTierPriceInStock.name}}"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml index 6e835f2e5e98b..b611d31782925 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -146,10 +146,15 @@ <!--Verify customer don't see updated virtual product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualTierPriceOutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{updateVirtualTierPriceOutOfStock.sku}}" stepKey="fillVirtualProductName"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <dontSee selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{updateVirtualTierPriceOutOfStock.name}}" stepKey="dontSeeVirtualProductName"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductName"> + <argument name="phrase" value="{{updateVirtualTierPriceOutOfStock.sku}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <argument name="productName" value="{{updateVirtualTierPriceOutOfStock.name}}"/> + </actionGroup> + </test> </tests> diff --git a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml index d6a5aa8b93572..8b9b78b67bc75 100644 --- a/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml +++ b/app/code/Magento/CatalogSearch/Test/Mftf/Test/MinimalQueryLengthForCatalogSearchTest.xml @@ -38,10 +38,14 @@ <comment userInput="Go to Storefront and search for product" stepKey="searchProdUsingMinQueryLength"/> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomePage"/> <comment userInput="Quick search by single character and avoid using ES stopwords" stepKey="commentQuickSearch"/> - <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="B" stepKey="fillAttribute"/> - <waitForPageLoad stepKey="waitForSearchTextBox"/> - <click selector="{{StorefrontQuickSearchResultsSection.searchTextBoxButton}}" stepKey="clickSearchTextBoxButton"/> - <waitForPageLoad stepKey="waitForSearch"/> - <see selector="{{StorefrontCategoryMainSection.productName}}" userInput="$$createProduct.name$$" stepKey="seeProductNameInCategoryPage"/> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <argument name="phrase" value="B"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> + <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductNameInCategoryPage"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> </test> </tests> From e93ac14f541dcf01585453c7921d68396be63e03 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 10 Dec 2020 10:17:44 +0200 Subject: [PATCH 037/242] AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest adjusted --- ...mpleProductWithRegularPriceInStockEnabledFlatTest.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml index c1b80b94179fa..018337d9e09d4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml @@ -8,18 +8,15 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest" deprecated="Use AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatCatalogTest instead"> + <test name="AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest"> <annotations> <stories value="Update Simple Product"/> - <title value="DEPRECACTED. Update Simple Product with Regular Price (In Stock) Enabled Flat"/> + <title value="Update Simple Product with Regular Price (In Stock) Enabled Flat"/> <description value="Test log in to Update Simple Product and Update Simple Product with Regular Price (In Stock) Enabled Flat"/> <testCaseId value="MC-10818"/> <severity value="CRITICAL"/> <group value="catalog"/> <group value="mtf_migrated"/> - <skip> - <issueId value="DEPRECATED">Use AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatCatalogTest instead</issueId> - </skip> </annotations> <before> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> @@ -140,4 +137,4 @@ <waitForPageLoad stepKey="waitForSearch"/> <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductEnabledFlat.name}}" stepKey="seeSimpleProductNameOnMagentoStorefrontPage"/> </test> -</tests> +</tests> \ No newline at end of file From 99cfcaa7cf5d6e26d53a23f13b466bd19c82ec3a Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 10 Dec 2020 10:18:46 +0200 Subject: [PATCH 038/242] refactored --- ...pdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml index 018337d9e09d4..aa1b1ae702914 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockEnabledFlatTest.xml @@ -137,4 +137,4 @@ <waitForPageLoad stepKey="waitForSearch"/> <see selector="{{StorefrontQuickSearchResultsSection.productLink}}" userInput="{{simpleProductEnabledFlat.name}}" stepKey="seeSimpleProductNameOnMagentoStorefrontPage"/> </test> -</tests> \ No newline at end of file +</tests> From 701a96a2df0ebefaefff6da3a45f25dde5931cb2 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 10 Dec 2020 17:25:01 +0200 Subject: [PATCH 039/242] refactored asserting product details on storefont --- ...tAdminManageStockOnEditPageActionGroup.xml | 23 +++++++++++ ...uctStockStatusOnProductPageActionGroup.xml | 21 ++++++++++ ...dminUpdateSimpleProductTieredPriceTest.xml | 38 ++++++++++--------- ...ceInStockVisibleInCatalogAndSearchTest.xml | 38 ++++++++++--------- ...arPriceInStockVisibleInCatalogOnlyTest.xml | 34 +++++++++-------- ...larPriceInStockVisibleInSearchOnlyTest.xml | 38 ++++++++++--------- ...gularPriceInStockWithCustomOptionsTest.xml | 36 ++++++++++-------- ...eProductWithRegularPriceOutOfStockTest.xml | 34 +++++++++-------- 8 files changed, 165 insertions(+), 97 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminManageStockOnEditPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductStockStatusOnProductPageActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminManageStockOnEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminManageStockOnEditPageActionGroup.xml new file mode 100644 index 0000000000000..5e993106b5a61 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminManageStockOnEditPageActionGroup.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="AssertAdminManageStockOnEditPageActionGroup"> + <annotations> + <description>Check if manageStock value is correct + (the Product Edit page->Advanced Inventory section should be opened in Admin prior this check).</description> + </annotations> + <arguments> + <argument name="manageStock" type="string"/> + </arguments> + + <see selector="{{AdminProductFormAdvancedInventorySection.manageStock}}" userInput="{{manageStock}}" stepKey="seeManageStock"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductStockStatusOnProductPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductStockStatusOnProductPageActionGroup.xml new file mode 100644 index 0000000000000..857d88ebc197c --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertStorefrontProductStockStatusOnProductPageActionGroup.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="AssertStorefrontProductStockStatusOnProductPageActionGroup"> + <annotations> + <description>Validates that the provided Product Stock Status is present and correct + (the Product Detail page should be opened on Storefront prior this check)</description> + </annotations> + <arguments> + <argument name="productStockStatus" type="string"/> + </arguments> + + <see selector="{{StorefrontProductInfoMainSection.productStockStatus}}" userInput="{{productStockStatus}}" stepKey="seeProductStockStatus"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index 300b312612253..0f10142ccbd52 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -6,7 +6,7 @@ */ --> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminUpdateSimpleProductTieredPriceTest"> <annotations> @@ -71,10 +71,10 @@ <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductTierPrice300InStock.weight}}" stepKey="fillSimpleProductWeight"/> <selectOption selector="{{AdminProductFormSection.productWeightSelect}}" userInput="{{simpleProductTierPrice300InStock.weightSelect}}" stepKey="selectProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <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" /> + <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> @@ -122,23 +122,27 @@ <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{simpleProductTierPrice300InStock.name}}" stepKey="seeSimpleProductNameOnCategoryPage"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductTierPrice300InStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductTierPrice300InStock.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductTierPrice300InStock.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductTierPrice300InStock.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductTierPrice300InStock.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductTierPrice300InStock.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeProductSku"> <argument name="productSku" value="{{simpleProductTierPrice300InStock.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductTierPrice300InStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductTierPrice300InStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductTierPrice300InStock.storefrontStatus}}"/> + </actionGroup> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductTierPrice300InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 320edba5feeff..93046bc624053 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -51,10 +51,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{simpleProductRegularPrice245InStock.status}}" stepKey="selectStockStatusInStock"/> <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice245InStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <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" /> + <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> @@ -85,7 +85,7 @@ <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPrice245InStock.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice245InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice245InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -102,23 +102,27 @@ <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{simpleProductRegularPrice245InStock.name}}" stepKey="seeSimpleProductNameOnCategoryPage"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductRegularPrice245InStock.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductRegularPrice245InStock.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductRegularPrice245InStock.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductRegularPrice245InStock.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductRegularPrice245InStock.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeSimpleProductSkuOnStoreFrontPage"> <argument name="productSku" value="{{simpleProductRegularPrice245InStock.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductRegularPrice245InStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductRegularPrice245InStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductRegularPrice245InStock.storefrontStatus}}"/> + </actionGroup> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 77c3e7548a3cf..5f0b14d9cd404 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -85,7 +85,7 @@ <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPrice32501InStock.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32501InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice32501InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -102,23 +102,27 @@ <see selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="seeSimpleProductNameOnCategoryPage"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32501InStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductRegularPrice32501InStock.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductRegularPrice32501InStock.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductRegularPrice32501InStock.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductRegularPrice32501InStock.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeProductSku"> <argument name="productSku" value="{{simpleProductRegularPrice32501InStock.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductRegularPrice32501InStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductRegularPrice32501InStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductRegularPrice32501InStock.storefrontStatus}}"/> + </actionGroup> <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32501InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index 39dab0b08915c..8e9040a371f52 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -51,10 +51,10 @@ <selectOption selector="{{AdminProductFormSection.stockStatus}}" userInput="{{simpleProductRegularPrice325InStock.status}}" stepKey="selectStockStatusInStock"/> <fillField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice325InStock.weight}}" stepKey="fillSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDown"/> - <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$initialCategoryEntity.name$$" stepKey="fillSearchForInitialCategory" /> + <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" /> + <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> @@ -85,7 +85,7 @@ <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPrice325InStock.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice325InStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice325InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> @@ -97,23 +97,27 @@ <dontSee selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{simpleProductRegularPrice325InStock.name}}" stepKey="dontSeeSimpleProductNameOnCategoryPage"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice325InStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductRegularPrice325InStock.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductRegularPrice325InStock.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductRegularPrice325InStock.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductRegularPrice325InStock.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductRegularPrice325InStock.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeProductSku"> <argument name="productSku" value="{{simpleProductRegularPrice325InStock.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductRegularPrice325InStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductRegularPrice325InStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductRegularPrice325InStock.storefrontStatus}}"/> + </actionGroup> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice325InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml index 670030d1d98ea..f9fc864f079e0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml @@ -98,7 +98,7 @@ <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPriceCustomOptions.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPriceCustomOptions.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPriceCustomOptions.urlKey}}" stepKey="seeUrlKey"/> @@ -117,23 +117,27 @@ <seeInField selector="{{AdminProductCustomizableOptionsSection.fillOptionValueSku(simpleProductCustomizableOption.title,'0')}}" userInput="{{simpleProductCustomizableOption.option_0_sku}}" stepKey="seeOptionSku"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPriceCustomOptions.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductRegularPriceCustomOptions.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductRegularPriceCustomOptions.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductRegularPriceCustomOptions.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductRegularPriceCustomOptions.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductRegularPriceCustomOptions.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeSimpleProductSkuOnStoreFrontPage"> <argument name="productSku" value="{{simpleProductRegularPriceCustomOptions.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductRegularPriceCustomOptions.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductRegularPriceCustomOptions.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductRegularPriceCustomOptions.storefrontStatus}}"/> + </actionGroup> <!--Verify customer see customizable options are Required --> <seeElement selector="{{StorefrontProductInfoMainSection.requiredCustomSelect(simpleProductCustomizableOption.title)}}" stepKey="verifyFirstCustomOptionIsRequired"/> @@ -153,7 +157,7 @@ <seeElement selector="{{StorefrontProductPageSection.successMsg}}" stepKey="seeYouAddedSimpleprod4ToYourShoppingCartSuccessSaveMessage"/> <seeElement selector="{{StorefrontMinicartSection.quantity(1)}}" stepKey="seeAddedProductQuantityInCart"/> <actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/> - <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{simpleProductRegularPriceCustomOptions.name}}" stepKey="seeProductNameInMiniCart"/> + <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{simpleProductRegularPriceCustomOptions.name}}" stepKey="seeProductNameInMiniCart"/> <see selector="{{StorefrontMinicartSection.miniCartItemsText}}" userInput="{{simpleProductRegularPriceCustomOptions.storefront_new_cartprice}}" stepKey="seeProductPriceInMiniCart"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 441bc9b8f8005..ae03f0f075e62 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -85,7 +85,7 @@ <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPrice32503OutOfStock.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32503OutOfStock.weight}}" stepKey="seeSimpleProductWeight"/> <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories" /> + <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32503OutOfStock.urlKey}}" stepKey="seeUrlKey"/> @@ -96,23 +96,27 @@ <dontSee selector="{{StorefrontCategoryMainSection.productLink}}" userInput="{{simpleProductRegularPrice32503OutOfStock.name}}" stepKey="dontSeeSimpleProductNameOnCategoryPage"/> <!-- Verify customer see updated simple product (from the above step) on the storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32503OutOfStock.urlKey)}}" stepKey="goToProductPage"/> - <waitForPageLoad stepKey="waitForStorefrontProductPageLoad"/> - <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{simpleProductRegularPrice32503OutOfStock.name}}" stepKey="seeSimpleProductNameOnStoreFrontPage"/> - <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="{{simpleProductRegularPrice32503OutOfStock.price}}" stepKey="seeSimpleProductPriceOnStoreFrontPage"/> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{simpleProductRegularPrice32503OutOfStock.urlKey}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="waitForStorefrontProductPageLoad"/> + + <actionGroup ref="StorefrontAssertProductNameOnProductPageActionGroup" stepKey="seeSimpleProductNameOnStoreFrontPage"> + <argument name="productName" value="{{simpleProductRegularPrice32503OutOfStock.name}}"/> + </actionGroup> + + <actionGroup ref="StorefrontAssertProductPriceOnProductPageActionGroup" stepKey="seeSimpleProductPriceOnStoreFrontPage"> + <argument name="productPrice" value="{{simpleProductRegularPrice32503OutOfStock.price}}"/> + </actionGroup> + <actionGroup ref="StorefrontAssertProductSkuOnProductPageActionGroup" stepKey="seeSimpleProductSkuOnStoreFrontPage"> <argument name="productSku" value="{{simpleProductRegularPrice32503OutOfStock.sku}}"/> </actionGroup> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productStockStatus}}" stepKey="productStockAvailableStatus"/> - <assertEquals stepKey="assertStockAvailableOnProductPage"> - <expectedResult type="string">{{simpleProductRegularPrice32503OutOfStock.storefrontStatus}}</expectedResult> - <actualResult type="variable">productStockAvailableStatus</actualResult> - </assertEquals> - <grabTextFrom selector="{{StorefrontProductInfoMainSection.productPrice}}" stepKey="productPriceAmount"/> - <assertEquals stepKey="assertOldPriceTextOnProductPage"> - <expectedResult type="string">${{simpleProductRegularPrice32503OutOfStock.price}}</expectedResult> - <actualResult type="variable">productPriceAmount</actualResult> - </assertEquals> + + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productStockAvailableStatus"/> + <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> + <argument name="productStockStatus" value="{{simpleProductRegularPrice32503OutOfStock.storefrontStatus}}"/> + </actionGroup> <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32503OutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> From 40cf39ef3153061e06b59a503c88cd261700a953 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 10 Dec 2020 17:33:44 +0200 Subject: [PATCH 040/242] refactored --- .../Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index 0f10142ccbd52..f05dde1902c68 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -6,7 +6,7 @@ */ --> -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminUpdateSimpleProductTieredPriceTest"> <annotations> From 631dc30f6ebbed20ed0555c8b8cf1078210160e3 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Sun, 13 Dec 2020 10:42:47 +0200 Subject: [PATCH 041/242] renamed ActionGroup --- ...efrontAssertProductNameIsNotOnProductMainPageActionGroup.xml | 2 +- ...eSimpleProductWithRegularPriceInStockDisabledProductTest.xml | 2 +- ...ProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml | 2 +- ...leProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 2 +- .../AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml | 2 +- ...lProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml | 2 +- ...oductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml | 2 +- ...ProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml | 2 +- ...WithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml | 2 +- ...tualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml | 2 +- ...uctWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml index 9492aabe1c6f3..ccda16f37085f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontAssertProductNameIsNotOnProductMainPageActionGroup.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="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup"> + <actionGroup name="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup"> <annotations> <description>Validates that the provided Product Name is NOT present on a Storefront page.</description> </annotations> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml index 2775876895499..38591b836e52a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockDisabledProductTest.xml @@ -87,7 +87,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductNameOnStorefrontPage"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductNameOnStorefrontPage"> <argument name="productName" value="{{simpleProductDisabled.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index 7f347a6280d91..dd8792e68af2b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -101,7 +101,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeSimpleProductNameOnMagentoStorefrontPage"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeSimpleProductNameOnMagentoStorefrontPage"> <argument name="productName" value="{{simpleProductNotVisibleIndividually.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 5b45c4dce8e5b..8946a86fef2ab 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -134,7 +134,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> <argument name="productName" value="{{simpleProductRegularPrice32501InStock.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 8caf2afb1b914..f440f714e8c39 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -124,7 +124,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeProductName"> <argument name="productName" value="{{simpleProductRegularPrice32503OutOfStock.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml index 469446cd702ce..cda4e092a444f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml @@ -122,7 +122,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> <argument name="productName" value="{{updateVirtualProductRegularPrice.name}}"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml index ac8b80045bdc0..1c23d2cd59f39 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInCategoryOnlyTest.xml @@ -128,7 +128,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> <argument name="productName" value="{{updateVirtualProductRegularPrice5OutOfStock.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml index 942079421e3aa..c738a589946c0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceOutOfStockVisibleInSearchOnlyTest.xml @@ -106,7 +106,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductLinkOnStorefrontPage"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductLinkOnStorefrontPage"> <argument name="productName" value="{{updateVirtualProductRegularPrice99OutOfStock.name}}"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml index c72fe4e8d8535..df2e7f530158f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithSpecialPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -136,7 +136,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductNameOnStorefrontPage"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductNameOnStorefrontPage"> <argument name="productName" value="{{updateVirtualProductSpecialPriceOutOfStock.name}}"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml index 1006ba0df12db..6d21178bbfa01 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceInStockVisibleInCategoryOnlyTest.xml @@ -152,7 +152,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> <argument name="productName" value="{{updateVirtualProductWithTierPriceInStock.name}}"/> </actionGroup> </test> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml index b611d31782925..ded8f7d03029e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithTierPriceOutOfStockVisibleInCategoryAndSearchTest.xml @@ -152,7 +152,7 @@ <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> - <actionGroup ref="StorefrontAssertProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> + <actionGroup ref="AssertStorefrontProductNameIsNotOnProductMainPageActionGroup" stepKey="dontSeeVirtualProductName"> <argument name="productName" value="{{updateVirtualTierPriceOutOfStock.name}}"/> </actionGroup> From f2ad426d2ef1435d012ec96ace2ac5d39d5b32f1 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 16 Dec 2020 14:57:37 +0200 Subject: [PATCH 042/242] MC-24262: Async multistore webapi test fails with elasticsearch on CI --- .../Model/AsyncScheduleMultiStoreTest.php | 160 ++++++++---------- 1 file changed, 75 insertions(+), 85 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php b/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php index 3f5d4c70a30ce..fa9e45daf4438 100644 --- a/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php +++ b/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php @@ -8,20 +8,20 @@ namespace Magento\WebapiAsync\Model; -use Magento\Catalog\Api\Data\ProductInterface as Product; -use Magento\TestFramework\MessageQueue\PreconditionFailedException; -use Magento\TestFramework\MessageQueue\PublisherConsumerController; -use Magento\TestFramework\MessageQueue\EnvironmentPreconditionException; -use Magento\TestFramework\TestCase\WebapiAbstract; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\ResourceModel\Product\Collection; +use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Phrase; use Magento\Framework\Registry; use Magento\Framework\Webapi\Exception; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\ObjectManagerInterface; -use Magento\Store\Model\Store; use Magento\Framework\Webapi\Rest\Request; +use Magento\Store\Model\Store; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\MessageQueue\EnvironmentPreconditionException; +use Magento\TestFramework\MessageQueue\PreconditionFailedException; +use Magento\TestFramework\MessageQueue\PublisherConsumerController; +use Magento\TestFramework\TestCase\WebapiAbstract; /** * Check async request for multistore product creation service, scheduling bulk @@ -86,10 +86,13 @@ class AsyncScheduleMultiStoreTest extends WebapiAbstract */ private $registry; + /** + * @inheritDoc + */ protected function setUp(): void { + $logFilePath = TESTS_TEMP_DIR . "/MessageQueueTestLog.txt"; $this->objectManager = Bootstrap::getObjectManager(); - $this->logFilePath = TESTS_TEMP_DIR . "/MessageQueueTestLog.txt"; $this->registry = $this->objectManager->get(Registry::class); $params = array_merge_recursive( @@ -97,16 +100,15 @@ protected function setUp(): void ['MAGE_DIRS' => ['cache' => ['path' => TESTS_TEMP_DIR . '/cache']]] ); - /** @var PublisherConsumerController publisherConsumerController */ $this->publisherConsumerController = $this->objectManager->create( PublisherConsumerController::class, [ 'consumers' => $this->consumers, - 'logFilePath' => $this->logFilePath, + 'logFilePath' => $logFilePath, 'appInitParams' => $params, ] ); - $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); try { $this->publisherConsumerController->initialize(); @@ -124,16 +126,11 @@ protected function setUp(): void /** * @dataProvider storeProvider * @magentoApiDataFixture Magento/Store/_files/core_fixturestore.php + * @param string|null $storeCode + * @return void */ - public function testAsyncScheduleBulkMultistore($storeCode) + public function testAsyncScheduleBulkMultistore($storeCode): void { - if ($storeCode === self::STORE_CODE_FROM_FIXTURE) { - /** @var \Magento\Config\Model\Config $config */ - $config = Bootstrap::getObjectManager()->get(\Magento\Config\Model\Config::class); - if (strpos($config->getConfigDataValue('catalog/search/engine'), 'elasticsearch') !== false) { - $this->markTestSkipped('MC-20452'); - } - } $product = $this->getProductData(); $this->_markTestAsRestOnly(); @@ -147,9 +144,9 @@ public function testAsyncScheduleBulkMultistore($storeCode) ); try { - /** @var Product $productModel */ + /** @var ProductInterface $productModel */ $productModel = $this->objectManager->create( - Product::class, + ProductInterface::class, ['data' => $product['product']] ); $this->productRepository->save($productModel); @@ -161,16 +158,21 @@ public function testAsyncScheduleBulkMultistore($storeCode) $this->clearProducts(); } - private function asyncScheduleAndTest($product, $storeCode = null) + /** + * @param array $product + * @param string|null $storeCode + * @return void + */ + private function asyncScheduleAndTest(array $product, $storeCode = null): void { - $sku = $product['product'][Product::SKU]; - $productName = $product['product'][Product::NAME]; - $newProductName = $product['product'][Product::NAME] . $storeCode; + $sku = $product['product'][ProductInterface::SKU]; + $productName = $product['product'][ProductInterface::NAME]; + $newProductName = $product['product'][ProductInterface::NAME] . $storeCode; $this->skus[] = $sku; - $product['product'][Product::NAME] = $newProductName; - $product['product'][Product::TYPE_ID] = 'virtual'; + $product['product'][ProductInterface::NAME] = $newProductName; + $product['product'][ProductInterface::TYPE_ID] = 'virtual'; $response = $this->updateProductAsync($product, $sku, $storeCode); @@ -197,14 +199,14 @@ private function asyncScheduleAndTest($product, $storeCode = null) $serviceInfo = [ 'rest' => [ 'resourcePath' => self::REST_RESOURCE_PATH . '/' . $sku, - 'httpMethod' => Request::HTTP_METHOD_GET + 'httpMethod' => Request::HTTP_METHOD_GET, ] ]; $storeResponse = $this->_webApiCall($serviceInfo, $requestData, null, $checkingStore); if ($checkingStore == $storeCode || $storeCode == self::STORE_CODE_ALL) { $this->assertEquals( $newProductName, - $storeResponse[Product::NAME], + $storeResponse[ProductInterface::NAME], sprintf( 'Product name in %s store is invalid after updating in store %s.', $checkingStore, @@ -214,7 +216,7 @@ private function asyncScheduleAndTest($product, $storeCode = null) } else { $this->assertEquals( $productName, - $storeResponse[Product::NAME], + $storeResponse[ProductInterface::NAME], sprintf( 'Product name in %s store is invalid after updating in store %s.', $checkingStore, @@ -225,6 +227,9 @@ private function asyncScheduleAndTest($product, $storeCode = null) } } + /** + * @inheritDoc + */ protected function tearDown(): void { $this->clearProducts(); @@ -232,7 +237,10 @@ protected function tearDown(): void parent::tearDown(); } - private function clearProducts() + /** + * @return void + */ + private function clearProducts(): void { $size = $this->objectManager->create(Collection::class) ->addAttributeToFilter('sku', ['in' => $this->skus]) @@ -270,7 +278,7 @@ private function clearProducts() /** * @return array */ - public function getProductData() + public function getProductData(): array { $productBuilder = function ($data) { return array_replace_recursive( @@ -280,23 +288,26 @@ public function getProductData() }; return [ - 'product' => - $productBuilder( - [ - Product::TYPE_ID => 'simple', - Product::SKU => 'multistore-sku-test-1', - Product::NAME => 'Test Name ', - ] - ), + 'product' => $productBuilder( + [ + ProductInterface::TYPE_ID => 'simple', + ProductInterface::SKU => 'multistore-sku-test-1', + ProductInterface::NAME => 'Test Name ', + ] + ), ]; } - public function storeProvider() + /** + * @return array + */ + public function storeProvider(): array { $dataSets = []; foreach ($this->stores as $store) { $dataSets[$store] = [$store]; } + return $dataSets; } @@ -306,28 +317,28 @@ public function storeProvider() * @param array $productData * @return array */ - private function getSimpleProductData($productData = []) + private function getSimpleProductData($productData = []): array { return [ - Product::SKU => isset($productData[Product::SKU]) - ? $productData[Product::SKU] : uniqid('sku-', true), - Product::NAME => isset($productData[Product::NAME]) - ? $productData[Product::NAME] : uniqid('sku-', true), - Product::VISIBILITY => 4, - Product::TYPE_ID => 'simple', - Product::PRICE => 3.62, - Product::STATUS => 1, - Product::TYPE_ID => 'simple', - Product::ATTRIBUTE_SET_ID => 4, + ProductInterface::SKU => isset($productData[ProductInterface::SKU]) + ? $productData[ProductInterface::SKU] : uniqid('sku-', true), + ProductInterface::NAME => isset($productData[ProductInterface::NAME]) + ? $productData[ProductInterface::NAME] : uniqid('sku-', true), + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'simple', + ProductInterface::PRICE => 3.62, + ProductInterface::STATUS => 1, + ProductInterface::ATTRIBUTE_SET_ID => 4, ]; } /** - * @param $requestData + * @param array $requestData + * @param string $sku * @param string|null $storeCode * @return mixed */ - private function updateProductAsync($requestData, $sku, $storeCode = null) + private function updateProductAsync(array $requestData, string $sku, $storeCode = null) { $serviceInfo = [ 'rest' => [ @@ -339,40 +350,19 @@ private function updateProductAsync($requestData, $sku, $storeCode = null) return $this->_webApiCall($serviceInfo, $requestData, null, $storeCode); } - public function assertProductCreation($product) + /** + * @param array $product + * @return bool + */ + public function assertProductCreation(array $product): bool { - $sku = $product['product'][Product::SKU]; + $sku = $product['product'][ProductInterface::SKU]; $collection = $this->objectManager->create(Collection::class) - ->addAttributeToFilter(Product::SKU, ['eq' => $sku]) - ->addAttributeToFilter(Product::TYPE_ID, ['eq' => 'virtual']) + ->addAttributeToFilter(ProductInterface::SKU, ['eq' => $sku]) + ->addAttributeToFilter(ProductInterface::TYPE_ID, ['eq' => 'virtual']) ->load(); $size = $collection->getSize(); return $size > 0; } - - /** - * Remove test store - * //phpcs:disable - */ - public static function tearDownAfterClass(): void - { - parent::tearDownAfterClass(); - //phpcs:enable - /** @var Registry $registry */ - $registry = Bootstrap::getObjectManager()->get(Registry::class); - - $registry->unregister('isSecureArea'); - $registry->register('isSecureArea', true); - - /** @var Store $store*/ - $store = Bootstrap::getObjectManager()->create(Store::class); - $store->load('fixturestore'); - if ($store->getId()) { - $store->delete(); - } - - $registry->unregister('isSecureArea'); - $registry->register('isSecureArea', false); - } } From 5559a51bccae19c3b032a3fe17e08047a67aacf8 Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 16 Dec 2020 18:20:29 +0200 Subject: [PATCH 043/242] Fix ftp_nlist for empty folders return false --- lib/internal/Magento/Framework/Filesystem/Io/Ftp.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php index 04df5fd3f3a6c..4bd3e49485681 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php @@ -313,9 +313,10 @@ public function chmod($filename, $mode) */ public function ls($grep = null) { - $ls = @ftp_nlist($this->_conn, '.'); + $ls = @ftp_nlist($this->_conn, '.') ?? []; $list = []; + foreach ($ls as $file) { $list[] = ['text' => $file, 'id' => $this->pwd() . '/' . $file]; } From c42d022322d7e6114d6a8cd4b7029adc5e44022a Mon Sep 17 00:00:00 2001 From: Nazar Klovanych <nazarn96@gmail.com> Date: Wed, 16 Dec 2020 18:27:40 +0200 Subject: [PATCH 044/242] Update Ftp.php --- lib/internal/Magento/Framework/Filesystem/Io/Ftp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php index 4bd3e49485681..0027329e7d54c 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php @@ -313,7 +313,7 @@ public function chmod($filename, $mode) */ public function ls($grep = null) { - $ls = @ftp_nlist($this->_conn, '.') ?? []; + $ls = @ftp_nlist($this->_conn, '.') ?: []; $list = []; From 5e35bb3739ca1fb526c6caf170d5c1d2e1a181d3 Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Thu, 17 Dec 2020 15:12:09 +0200 Subject: [PATCH 045/242] Fixed failed integration test --- .../Magento/Csp/Model/Collector/ConfigCollectorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php b/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php index 2d8cbbeedeab9..cf6287ed5b4e1 100644 --- a/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php +++ b/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php @@ -62,9 +62,9 @@ private function getExpectedPolicies(): array [], true ), - 'font-src' => new FetchPolicy('font-src', false, [], [], true), + 'font-src' => new FetchPolicy('font-src', false, [], ['data'], true), 'frame-src' => new FetchPolicy('frame-src', false, [], [], true, false, false, [], [], true), - 'img-src' => new FetchPolicy('img-src', false, [], [], true), + 'img-src' => new FetchPolicy('img-src', false, [], ['data'], true), 'manifest-src' => new FetchPolicy('manifest-src', false, [], [], true), 'media-src' => new FetchPolicy('media-src', false, [], [], true), 'object-src' => new FetchPolicy('object-src', false, [], [], true), From e5444ad190e86c06855006518fb9b32486ca2d0a Mon Sep 17 00:00:00 2001 From: Vova Yatsyuk <vova.yatsyuk@gmail.com> Date: Thu, 17 Dec 2020 16:31:44 +0200 Subject: [PATCH 046/242] Add missing vatid field. It was copied from nearby address/edit.phtml template --- .../view/frontend/templates/form/register.phtml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml index 5e58f94683ec1..1d25a601c5523 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/register.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/register.phtml @@ -131,6 +131,23 @@ $formData = $block->getFormData(); </div> </div> + <?php if ($addressHelper->isVatAttributeVisible()): ?> + <?php $_vatidValidationClass = $addressHelper->getAttributeValidationClass('vat_id'); ?> + <div class="field taxvat"> + <label class="label" for="vat_id"> + <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('vat_id') ?></span> + </label> + <div class="control"> + <input type="text" + name="vat_id" + value="<?= $escaper->escapeHtmlAttr($formData->getVatId()) ?>" + title="<?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('vat_id') ?>" + class="input-text <?= $escaper->escapeHtmlAttr($_vatidValidationClass) ?>" + id="vat_id"> + </div> + </div> + <?php endif; ?> + <div class="field country required"> <label for="country" class="label"> <span><?= /* @noEscape */ $block->getAttributeData()->getFrontendLabel('country_id') ?></span> From 3a808ffdac1301bfa61a2add14d41e59b5a3bd0f Mon Sep 17 00:00:00 2001 From: Sergiy Vasiutynskyi <s.vasiutynskyi@atwix.com> Date: Thu, 17 Dec 2020 16:10:03 +0200 Subject: [PATCH 047/242] Removed usage or changed value of CliIndexerReindexActionGroup action group for Catalog module --- .../Test/AddOutOfStockProductToCompareListTest.xml | 4 ++-- .../Mftf/Test/AdminAddInStockProductToTheCartTest.xml | 5 +---- ...CheckCustomAttributeValuesAfterProductSaveTest.xml | 4 +--- .../AdminSimpleProductImagesTest.xml | 4 +--- .../AdminUpdateFlatCategoryNameAndDescriptionTest.xml | 11 +++-------- .../Test/AdminUpdateSimpleProductTieredPriceTest.xml | 5 +---- ...gularPriceInStockVisibleInCatalogAndSearchTest.xml | 5 +---- ...ithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 5 +---- .../Test/Mftf/Test/CheckTierPricingOfProductsTest.xml | 5 +---- .../EndToEndB2CGuestUserTest.xml | 5 +---- ...ProductAvailableAfterEnablingSubCategoriesTest.xml | 2 +- ...toreFrontProductsDisplayUsingElasticSearchTest.xml | 4 +--- .../Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml | 4 +--- .../StoreFrontRecentlyViewedAtStoreViewLevelTest.xml | 4 +--- ...refrontCheckDefaultNumberProductsToDisplayTest.xml | 5 +---- .../StorefrontProductNameWithHTMLEntitiesTest.xml | 4 +--- ...oryProductAndProductCategoryPartialReindexTest.xml | 4 +--- 17 files changed, 20 insertions(+), 60 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 92be79fdfe720..212400ac4dd6e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -52,8 +52,8 @@ <!--Clear cache and reindex--> <comment userInput="Clear cache and reindex" stepKey="cleanCache"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> -</actionGroup> + <argument name="indices" value="catalog_product_price"/> + </actionGroup> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml index 94d3b46aaa5f1..73019bb5ec0e0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml @@ -58,10 +58,7 @@ <actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickOnDoneButton"/> <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickOnSaveButton"/> <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the product." stepKey="messageYouSavedTheProductIsShown"/> - <!--Clear cache and reindex--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml index 0bdf19c9b8950..ca0616213c593 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml @@ -33,9 +33,7 @@ </createData> <!-- Create simple product --> <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexCatalogSearch"> - <argument name="indices" value="catalogsearch_fulltext"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindexCatalogSearch"/> <!-- Login to Admin page --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml index de116b26d1414..8a33f6132aeb9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml @@ -141,9 +141,7 @@ <!-- Save the second product --> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct2"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml index 27a834833ed76..2124efed31293 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml @@ -34,10 +34,7 @@ <magentoCLI stepKey="setFlatCatalogCategory" command="config:set catalog/frontend/flat_catalog_category 1"/> <!--Open Index Management Page and Select Index mode "Update by Schedule" --> <magentoCLI stepKey="setIndexerMode" command="indexer:set-mode" arguments="schedule" /> - <!--Run full reindex and clear caches --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> @@ -45,9 +42,7 @@ <after> <magentoCLI stepKey="setFlatCatalogCategory" command="config:set catalog/frontend/flat_catalog_category 0 "/> <magentoCLI stepKey="setIndexerMode" command="indexer:set-mode" arguments="realtime" /> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="indexerReindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="indexerReindex"/> <deleteData stepKey="deleteCategory" createDataKey="createCategory" /> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewEn"> <argument name="customStore" value="customStoreEN"/> @@ -71,7 +66,7 @@ <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="seeSuccessMessage"/> <!--Run full reindex and clear caches --> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="catalog_category_flat"/> </actionGroup> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index 300b312612253..95d5e4d349478 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -26,10 +26,7 @@ </createData> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> - <!--TODO: REMOVE AFTER FIX MC-21717 --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value="full_page"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 320edba5feeff..1735dc692ed3b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -91,10 +91,7 @@ <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice245InStock.urlKey}}" stepKey="seeUrlKey"/> - <!--Run re-index task --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Verify customer see updated simple product link on category page --> <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 77c3e7548a3cf..bd3160248682e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -91,10 +91,7 @@ <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32501InStock.urlKey}}" stepKey="seeUrlKey"/> - <!--Run re-index task --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Verify customer see updated simple product link on category page --> <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 5f7e9c4225c00..2095d56ce6c59 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -332,10 +332,7 @@ <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <!--Do reindex and flush cache--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml index ff68bba78cae8..aed2976df8f73 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml @@ -56,10 +56,7 @@ <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> </after> - <!--Re-index--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Step 1: User browses catalog --> <comment userInput="Start of browsing catalog" stepKey="startOfBrowsingCatalog"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index 7fd752d7df98d..b5980cf977791 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -50,7 +50,7 @@ <!--Run re-index task--> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="cataloginventory_stock"/> </actionGroup> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomepage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml index cde7b14614f8e..3d3867d1efcf1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml @@ -114,9 +114,7 @@ </createData> <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="performReindex"> - <argument name="indices" value="catalogsearch_fulltext"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="performReindex"/> <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanFullPageCache"> <argument name="tags" value="full_page"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml index e1b5aca6382e9..64ad348257853 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml @@ -74,9 +74,7 @@ </actionGroup> <!-- Logout Admin --> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletion"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml index 0117493906de1..4d04a25c8d12f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml @@ -66,9 +66,7 @@ <!-- Logout Admin --> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletion"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml index a73bd5a533ad0..ca561e4af70de 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml @@ -187,10 +187,7 @@ <seeInField selector="{{AdminCatalogStorefrontConfigSection.productsPerPageAllowedValues}}" userInput="12,24,36" stepKey="seeDefaultValueAllowedNumberProductsPerPage"/> <seeInField selector="{{AdminCatalogStorefrontConfigSection.productsPerPageDefaultValue}}" userInput="12" stepKey="seeDefaultValueProductPerPage"/> - <!-- Perform reindex and flush cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml index 2156178ea88d0..9819357704d44 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml @@ -33,9 +33,7 @@ </after> <!--Run re-index task--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Check product in category listing--> <amOnPage url="{{StorefrontCategoryPage.url($$createCategoryOne.name$$)}}" stepKey="navigateToCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml index ce04b377300f8..cf1bb065349b6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml @@ -65,9 +65,7 @@ <after> <!-- Change "Category Products" and "Product Categories" indexers to "Update on Save" mode --> <magentoCLI command="indexer:set-mode" arguments="realtime" stepKey="setRealtimeMode"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Delete data --> <deleteData createDataKey="productA" stepKey="deleteProductA"/> From 37e8487aca8692b89c9657215ea0c9618cc5d967 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 17 Dec 2020 17:55:16 +0200 Subject: [PATCH 048/242] added AdminClickRefundOfflineOnMemoDetailPageActionGroup --- ...dableProductLinkAfterPartialRefundTest.xml | 4 ++-- ...kRefundOfflineOnNewMemoPageActionGroup.xml | 19 +++++++++++++++++++ ...reateCreditMemoBankTransferPaymentTest.xml | 4 ++-- ...AdminCreateCreditMemoPartialRefundTest.xml | 4 ++-- ...nCreateCreditMemoWithPurchaseOrderTest.xml | 4 ++-- .../Test/Mftf/Test/EndToEndB2CAdminTest.xml | 4 ++-- 6 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml index b89aa7d126686..41fc2850e00ff 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml @@ -98,8 +98,8 @@ <argument name="rowNumber" value="1"/> </actionGroup> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <actionGroup ref="StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup" stepKey="dontSeeStorefrontMyAccountDownloadableProductsLink"> <argument name="product" value="$$createDownloadableProduct$$"/> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml new file mode 100644 index 0000000000000..21ca2d51a364e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.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="AdminClickRefundOfflineOnNewMemoPageActionGroup"> + <annotations> + <description>Click the Refund Offline button on the New Memo page</description> + </annotations> + <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccesMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You created the credit memo." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml index 6ed8510db777c..9d1daf0d2ded1 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml @@ -85,8 +85,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <see selector="{{AdminIndexManagementSection.successMessage}}" userInput="You created the credit memo." stepKey="assertRefundSuccessCreateMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml index 68301187d3d31..5d2f76b80e3f8 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml @@ -78,8 +78,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <waitForElementVisible selector="{{AdminIndexManagementSection.successMessage}}" stepKey="waitForSuccessMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml index 141fa2a9e5d06..32c3a5e0a5846 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml @@ -88,8 +88,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <see selector="{{AdminIndexManagementSection.successMessage}}" userInput="You created the credit memo." stepKey="assertRefundSuccessCreateMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml index 6ba1c3ac3deec..2a3284e7e8e35 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml @@ -140,8 +140,8 @@ <argument name="billingAddress" value="US_Address_TX"/> </actionGroup> <!--Submit credit memo--> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline" after="verifyOrderCreditMemoInformation"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the credit memo." stepKey="seeCreditMemoSuccess" after="clickRefundOffline"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline" after="verifyOrderCreditMemoInformation"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeCreditMemoSuccess" after="clickRefundOffline"/> <click selector="{{AdminOrderDetailsOrderViewSection.creditMemos}}" stepKey="clickOrderCreditMemosTab" after="seeCreditMemoSuccess"/> <waitForLoadingMaskToDisappear stepKey="waitForCreditMemoTabLoadingMask" after="clickOrderCreditMemosTab"/> <see selector="{{AdminOrderCreditMemosTabSection.gridRow('1')}}" userInput="{{Simple_US_Customer.firstname}}" stepKey="seeOrderCreditMemoInTabGrid" after="waitForCreditMemoTabLoadingMask"/> From 01eb68279d3f49adb66c14c351c5dd9576c39b6f Mon Sep 17 00:00:00 2001 From: Oleg Aleksin <olega@ven.com> Date: Fri, 18 Dec 2020 10:45:17 +0200 Subject: [PATCH 049/242] Fix issue with logging each cookie as separate context --- .../Magento/Framework/Stdlib/Cookie/PhpCookieManager.php | 5 ++++- .../Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php index a5fe6f6c61506..64f04c62bbf64 100644 --- a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php +++ b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php @@ -212,7 +212,10 @@ private function checkAbilityToSendCookie($name, $value) if ($numCookies > static::MAX_NUM_COOKIES) { $this->logger->warning( new Phrase('Unable to send the cookie. Maximum number of cookies would be exceeded.'), - array_merge($_COOKIE, ['user-agent' => $this->httpHeader->getHttpUserAgent()]) + [ + 'cookies' => $_COOKIE, + 'user-agent' => $this->httpHeader->getHttpUserAgent() + ] ); } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php index e41cbdfe51638..87e10981c802c 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php @@ -565,7 +565,10 @@ public function testSetTooManyCookies() ->method('warning') ->with( new Phrase('Unable to send the cookie. Maximum number of cookies would be exceeded.'), - array_merge($_COOKIE, ['user-agent' => $userAgent]) + [ + 'cookies' => $_COOKIE, + 'user-agent' => $userAgent + ] ); $this->cookieManager->setPublicCookie( From 73ef59b9e0a3a1f7ada74bdd00f7168d7106ace1 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Fri, 18 Dec 2020 16:43:36 +0200 Subject: [PATCH 050/242] magento/magento2#30950 allow login without redirect when using a secret key --- app/code/Magento/Backend/App/Action/Plugin/Authentication.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/App/Action/Plugin/Authentication.php b/app/code/Magento/Backend/App/Action/Plugin/Authentication.php index 4b25e9921e404..519db00d6439d 100644 --- a/app/code/Magento/Backend/App/Action/Plugin/Authentication.php +++ b/app/code/Magento/Backend/App/Action/Plugin/Authentication.php @@ -225,7 +225,8 @@ protected function _redirectIfNeededAfterLogin(\Magento\Framework\App\RequestInt // Checks, whether secret key is required for admin access or request uri is explicitly set if ($this->_url->useSecretKey()) { - $requestUri = $this->_url->getUrl('*/*/*', ['_current' => true]); + $requestParts = explode('/', trim($request->getRequestUri(), '/'), 2); + $requestUri = $this->_url->getUrl(array_pop($requestParts)); } elseif ($request) { $requestUri = $request->getRequestUri(); } From d01133d13f6d130d5497a891a4e0ea3195a7bcac Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Fri, 18 Dec 2020 18:49:23 +0200 Subject: [PATCH 051/242] MFTF has been added. --- .../StorefrontCustomerAddressSection.xml | 1 + ...IdAtAccountCreateWithMultishipmentTest.xml | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection/StorefrontCustomerAddressSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection/StorefrontCustomerAddressSection.xml index c1e0ac6573be7..533a1d91b9c77 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection/StorefrontCustomerAddressSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDashboardAccountInformationSection/StorefrontCustomerAddressSection.xml @@ -19,6 +19,7 @@ <element name="stateProvinceFill" type="input" selector="#region"/> <element name="zip" type="input" selector="#zip"/> <element name="country" type="select" selector="#country"/> + <element name="vatId" type="input" selector="#vat_id"/> <element name="saveAddress" type="button" selector="[data-action='save-address']" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml new file mode 100644 index 0000000000000..efaf4d7dc639d --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml @@ -0,0 +1,55 @@ +<?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="StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest"> + <annotations> + <features value="Multishipment"/> + <stories value="Checking vat id field at account create page with 'Check Out with Multiple Addresses'"/> + <title value="Checking vat id field at account create page with 'Check Out with Multiple Addresses'"/> + <description value="'VAT Number' field should be available at create account page if 'Show VAT Number on Storefront' is Yes"/> + <severity value="MAJOR"/> + <testCaseId value="MC-40016"/> + <group value="Multishipment"/> + </annotations> + <before> + <magentoCLI command="config:set customer/create_account/vat_frontend_visibility 1" stepKey="showVatNumberOnStorefrontYes"/> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheBefore"> + <argument name="tags" value="config"/> + </actionGroup> + <createData stepKey="category" entity="SimpleSubCategory"/> + <createData stepKey="product1" entity="SimpleProduct"> + <requiredEntity createDataKey="category"/> + </createData> + </before> + <!-- Add product to the cart --> + <amOnPage url="$$product1.name$$.html" stepKey="goToProductPage"/> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> + <argument name="productName" value="$$product1.name$$"/> + </actionGroup> + <!-- Check Out with Multiple Addresses --> + <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> + <waitForElementVisible selector="{{MultishippingSection.shippingMultipleCheckout}}" stepKey="waitMultipleAddressShippingButton"/> + <click selector="{{MultishippingSection.shippingMultipleCheckout}}" stepKey="clickToMultipleAddressShippingButton"/> + <!--Create an account--> + <waitForElementVisible selector="{{StorefrontCustomerSignInPopupFormSection.createAnAccount}}" stepKey="waitCreateAnAccountButton"/> + <click selector="{{StorefrontCustomerSignInPopupFormSection.createAnAccount}}" stepKey="clickOnCreateAnAccountButton"/> + <waitForPageLoad stepKey="waitForCreateAccountPageToLoad"/> + <!--Check the VAT Number field--> + <seeElement selector="{{StorefrontCustomerAddressSection.vatId}}" stepKey="assertVatIdField"/> + <after> + <magentoCLI command="config:set customer/create_account/vat_frontend_visibility 0" stepKey="showVatNumberOnStorefrontNo"/> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfter"> + <argument name="tags" value="config"/> + </actionGroup> + <deleteData stepKey="deleteCategory" createDataKey="category"/> + <deleteData stepKey="deleteProduct1" createDataKey="product1"/> + </after> + </test> +</tests> From 628a1e4247dabe95ed2e343a37ed945a39811b7f Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Mon, 21 Dec 2020 14:36:21 +0530 Subject: [PATCH 052/242] Updated wishlist graphql readme file --- app/code/Magento/WishlistGraphQl/README.md | 44 ++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/WishlistGraphQl/README.md b/app/code/Magento/WishlistGraphQl/README.md index 9121593e6a759..3bab2a76bd5eb 100644 --- a/app/code/Magento/WishlistGraphQl/README.md +++ b/app/code/Magento/WishlistGraphQl/README.md @@ -1,4 +1,42 @@ -# WishlistGraphQl +# Magento_WishlistGraphQl module -**WishlistGraphQl** provides type information for the GraphQl module -to generate wishlist fields. +The **Magento_WishlistGraphQl** module adds, removes, and updates products on the wishlist. + +The **Magento_WishlistGraphQl** module extends **Magento_GraphQl** and **Magento_Wishlist** modules. The module provides type and resolver information for GraphQL API. + +## Installation details + +Before installing this module, note that the **Magento_WishlistGraphQl** is dependent on the following modules: + +- Magento_Catalog +- Magento_Checkout +- Magento_Customer +- Magento_CustomerGraphQl +- Magento_Directory +- Magento_GiftMessage +- Magento_GraphQl +- Magento_Quote +- Magento_Sales +- Magento_Store + +For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Extensibility + +Extension developers can interact with the Magento_WishlistGraphQl module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WishlistGraphQl module. + +## Additional information + +For more information about the **Magento_WishlistGraphQl** [Queries](#queries) and [Mutations](#mutations) see below: + +### Queries {#queries} + +- [`wishlist`](https://devdocs.magento.com/guides/v2.4/graphql/queries/wishlist.html) + +### Mutations {#mutations} + +- [`addProductsToWishlist`](https://devdocs.magento.com/guides/v2.4/graphql/mutations/add-products-to-wishlist.html) +- [`removeProductsFromWishlist`](https://devdocs.magento.com/guides/v2.4/graphql/mutations/remove-products-from-wishlist.html) +- [`updateProductsInWishlist`](https://devdocs.magento.com/guides/v2.4/graphql/mutations/update-products-in-wishlist.html) From 2a712558d59eac9d4474c3e62142976b5c53dab1 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 21 Dec 2020 12:02:19 +0200 Subject: [PATCH 053/242] refactored AdminSortProductsGridByActionGroup --- ...ngeWebSiteAssignedToProductActionGroup.xml | 21 ++++++++++ .../AdminSortProductsGridByActionGroup.xml | 22 +++++++++++ .../Mftf/Test/AdminSortingByWebsitesTest.xml | 39 +++++++++---------- 3 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml new file mode 100644 index 0000000000000..76a0af8f63fd5 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.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="AdminChangeWebSiteAssignedToProductActionGroup" extends="AddWebsiteToProductActionGroup"> + <annotations> + <description>Extends AddWebsiteToProductActionGroup. Changes website assigned to product from websiteToDeselect to website</description> + </annotations> + <arguments> + <argument name="websiteToDeselect" type="string"/> + </arguments> + + <uncheckOption selector="{{ProductInWebsitesSection.website(websiteToDeselect)}}" stepKey="uncheckWebsite" after="checkWebsite"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml new file mode 100644 index 0000000000000..92c714c2478b0 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.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="AdminSortProductsGridByActionGroup"> + <annotations> + <description>Sorts the Product Grid by field</description> + </annotations> + <arguments> + <argument name="field" type="string"/> + </arguments> + + <click selector="{{AdminProductGridSection.columnHeader(field)}}" stepKey="clickWebsitesHeaderToSort"/> + <waitForLoadingMaskToDisappear stepKey="waitForApplyingChanges"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml index 73aeed3af4fb0..76843b3a40fcb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml @@ -25,7 +25,7 @@ </createData> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <!--Create new website --> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createAdditionalWebsite"> <argument name="newWebsiteName" value="{{customWebsite.name}}"/> <argument name="websiteCode" value="{{customWebsite.code}}"/> @@ -54,31 +54,30 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <!--Assign Custom Website to Simple Product --> - <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToCatalogProductGrid"/> - - <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFiltersInitial"/> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="navigateToCatalogProductGrid"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickClearFiltersInitial"/> <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="assignCustomWebsiteToProduct"> <argument name="product" value="$$productAssignedToCustomWebsite$$"/> </actionGroup> - <scrollTo selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="scrollToWebsites"/> - <conditionalClick selector="{{ProductInWebsitesSection.sectionHeader}}" dependentSelector="{{AdminProductContentSection.sectionHeaderShow}}" visible="false" stepKey="expandSection"/> - <waitForPageLoad stepKey="waitForPageOpened"/> - <uncheckOption selector="{{ProductInWebsitesSection.website(_defaultWebsite.name)}}" stepKey="deselectMainWebsite"/> - <checkOption selector="{{ProductInWebsitesSection.website(customWebsite.name)}}" stepKey="selectWebsite"/> - - <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickSave"/> - <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="seeSaveProductMessageAgain"/> + <actionGroup ref="AdminChangeWebSiteAssignedToProductActionGroup" stepKey="scrollToWebsites"> + <argument name="website" value="{{customWebsite.name}}"/> + <argument name="websiteToDeselect" value="{{_defaultWebsite.name}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="expandSection"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageOpened"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="deselectMainWebsite"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectWebsite"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSaveProductMessageAgain"/> - <!--Navigate To Product Grid To Check Website Sorting--> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToCatalogProductGridToSortByWebsite"/> - - <!--Sorting works (By Websites) ASC--> - <click selector="{{AdminProductGridSection.columnHeader('Websites')}}" stepKey="clickWebsitesHeaderToSortAsc"/> + <actionGroup ref="AdminSortProductsGridByActionGroup" stepKey="clickWebsitesHeaderToSortAsc"> + <argument name="field" value="Websites"/> + </actionGroup> <see selector="{{AdminProductGridSection.productGridContentsOnRow('1')}}" userInput="Main Website" stepKey="checkIfProduct1WebsitesAsc"/> - - <!--Sorting works (By Websites) DESC--> - <click selector="{{AdminProductGridSection.columnHeader('Websites')}}" stepKey="clickWebsitesHeaderToSortDesc"/> + <actionGroup ref="AdminSortProductsGridByActionGroup" stepKey="clickWebsitesHeaderToSortDesc"> + <argument name="field" value="Websites"/> + </actionGroup> <see selector="{{AdminProductGridSection.productGridContentsOnRow('1')}}" userInput="{{customWebsite.name}}" stepKey="checkIfProduct1WebsitesDesc"/> </test> </tests> From c16f995ae5a10e037841f2624ebf1e6987f5cba9 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Mon, 21 Dec 2020 16:54:17 +0530 Subject: [PATCH 054/242] Updated wishlist analytics readme file --- app/code/Magento/WishlistAnalytics/README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/WishlistAnalytics/README.md b/app/code/Magento/WishlistAnalytics/README.md index 275acf0796286..32cf1d35bbd06 100644 --- a/app/code/Magento/WishlistAnalytics/README.md +++ b/app/code/Magento/WishlistAnalytics/README.md @@ -1,3 +1,18 @@ # Magento_WishlistAnalytics module -The Magento_WishlistAnalytics module configures data definitions for a data collection related to the Wishlist module entities to be used in [Advanced Reporting](https://devdocs.magento.com/guides/v2.3/advanced-reporting/modules.html). +The **Magento_WishlistAnalytics** module configures data definitions for a data collection related to the Wishlist module entities to be used in [Advanced Reporting](https://devdocs.magento.com/guides/v2.4/advanced-reporting/modules.html). + +## Installation details + +Before installing this module, note that the **Magento_WishlistAnalytics** is dependent on the following modules: + +- Magento_Analytics +- Magento_Wishlist + +For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Extensibility + +Extension developers can interact with the Magento_WishlistAnalytics module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WishlistAnalytics module. From 217c32c91a960a28f648efe9653fc3517af65779 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Mon, 21 Dec 2020 13:54:58 +0200 Subject: [PATCH 055/242] redirect to backend if request uri isn't valid --- app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php | 5 +++++ app/code/Magento/User/Controller/Adminhtml/User/Save.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php b/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php index 18de812b2fa9d..16be2cf1343eb 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Auth/Login.php @@ -48,6 +48,11 @@ public function execute() return $this->getRedirect($this->_backendUrl->getStartupPageUrl()); } + $requestUrl = $this->getRequest()->getUri(); + if (!$requestUrl->isValid()) { + return $this->getRedirect($this->getUrl('*')); + } + return $this->resultPageFactory->create(); } diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Save.php b/app/code/Magento/User/Controller/Adminhtml/User/Save.php index 521c09f7b7707..72024a85bef13 100644 --- a/app/code/Magento/User/Controller/Adminhtml/User/Save.php +++ b/app/code/Magento/User/Controller/Adminhtml/User/Save.php @@ -105,7 +105,7 @@ public function execute() $this->getSecurityCookie()->setLogoutReasonCookie( \Magento\Security\Model\AdminSessionsManager::LOGOUT_REASON_USER_LOCKED ); - $this->_redirect('adminhtml/*/'); + $this->_redirect('*'); } catch (NotificationExceptionInterface $exception) { $this->messageManager->addErrorMessage($exception->getMessage()); } catch (\Magento\Framework\Exception\AuthenticationException $e) { From 6e3b5b09fc4208c6a0545b70a0c2c8771f491744 Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Mon, 21 Dec 2020 13:56:25 +0200 Subject: [PATCH 056/242] added a comment to prevent bic --- .../Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml index 4996992c70245..c7bfdd8bb9e98 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminNavigateWhileUserExpiredTest.xml @@ -48,6 +48,7 @@ <wait time="120" stepKey="waitForUserToExpire"/> <actionGroup ref="AdminOpenCustomersGridActionGroup" stepKey="navigateToCustomers"/> <!-- Confirm that user is logged out --> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAdminLoginUrl"/> <seeElement selector="{{AdminLoginFormSection.loginBlock}}" stepKey="assertAdminLoginPageIsAvailable"/> <!-- Delete created user --> From cfbc08c8957ab7a23fc3a6c074303950c93e126c Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Tue, 22 Dec 2020 10:22:40 +0530 Subject: [PATCH 057/242] Removed extensibility content from the readme file. --- app/code/Magento/WishlistAnalytics/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/WishlistAnalytics/README.md b/app/code/Magento/WishlistAnalytics/README.md index 32cf1d35bbd06..5bbd19416ac82 100644 --- a/app/code/Magento/WishlistAnalytics/README.md +++ b/app/code/Magento/WishlistAnalytics/README.md @@ -10,9 +10,3 @@ Before installing this module, note that the **Magento_WishlistAnalytics** is de - Magento_Wishlist For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). - -## Extensibility - -Extension developers can interact with the Magento_WishlistAnalytics module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). - -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WishlistAnalytics module. From 6cb297ba167aa95aaa0f2f9fa000292dcfaabd1a Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Tue, 22 Dec 2020 13:27:50 +0530 Subject: [PATCH 058/242] Updated wishlist readme file --- app/code/Magento/Wishlist/README.md | 102 +++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Wishlist/README.md b/app/code/Magento/Wishlist/README.md index 1caed125814e7..67fbef6771cba 100644 --- a/app/code/Magento/Wishlist/README.md +++ b/app/code/Magento/Wishlist/README.md @@ -1,2 +1,100 @@ -The Magento_Wishlist implements the Wishlist functionality. -This allows customers to create a list of products that they can add to their shopping cart to be purchased at a later date, or share with friends. +# Magento_Wishlist module + +The **Magento_Wishlist** module implements the Wishlist functionality. + +This module allows customers to create a list of products that they can add to their shopping cart to be purchased at a later date, or share with friends. + +## Installation details + +Before installing this module, note that the **Magento_Wishlist** is dependent on the following modules: + +- Magento_Captcha +- Magento_Catalog +- Magento_Customer + +Before disabling or uninstalling this module, please consider the following dependencies: + +- Magento_WishlistAnalytics + +Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Structure + +`Pricing/` - the directory that contain solutions for configurable and downloadable product price. + +For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). + +## Extensibility + +Extension developers can interact with the Magento_Wishlist module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_Wishlist module. + +### Events + +The module dispatches the following events: + +- `product_option_renderer_init` event in the `\Magento\Wishlist\Block\Customer\Wishlist\Item\Options::_construct()` method. Parameters: + - `block` is a Wishlist block customer items (`\Magento\Wishlist\Block\Customer\Wishlist\Item\Options` class). +- `rss_wishlist_xml_callback` event in the `\Magento\Wishlist\Model\Rss\Wishlist::getRssData()` method. Parameters: + - `$args` is a array of product object (`\Magento\Catalog\Model\Product` class). +- `wishlist_add_item` event in the `\Magento\Wishlist\Model\Wishlist::addItem()` method. Parameters: + - `item` is an item object (`\Magento\Wishlist\Model\Item` class). +- `wishlist_add_product` event in the `\Magento\Wishlist\Controller\Index\Add::execute()` method. Parameters: + - `wishlist` is a Wishlist object (`\Magento\Wishlist\Model\Wishlist` class). + - `product` is a product object (`\Magento\Catalog\Api\Data\ProductInterface` class). + - `item` is an item object (`\Magento\Wishlist\Model\Item` class). +- `wishlist_item_collection_products_after_load` event in the `\Magento\Wishlist\Model\ResourceModel\Item\Collection::_assignProducts()` method. Parameters: + - `product_collection` is a product collection object (`\Magento\Catalog\Model\ResourceModel\Product\Collection` class). +- `wishlist_items_renewed` event in the `\Magento\Wishlist\Helper\Data::calculate()` method. +- `wishlist_product_add_after` event in the `\Magento\Wishlist\Model\Wishlist::addNewItem()` method. Parameters: + - `items` is an array of item object (`\Magento\Wishlist\Model\Item` class). +- `wishlist_share` event in the `\Magento\Wishlist\Controller\Index\Send::execute()` method. Parameters: + - `wishlist` is a Wishlist object (`\Magento\Wishlist\Model\Wishlist` class). +- `wishlist_update_item` event in the `\Magento\Wishlist\Controller\Index\UpdateItemOptions::execute()` method. Parameters: + - `wishlist` is a Wishlist object (`\Magento\Wishlist\Model\Wishlist` class). + - `product` is a product object (`\Magento\Catalog\Api\Data\ProductInterface` class). + - `item` is an item object (`\Magento\Wishlist\Model\Item` class). + +For information about the event system in Magento 2, see [Events and observers](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/events-and-observers.html#events). + +### Layouts + +This module introduces the following layouts and layout handles in the directories: + +- `view/adminhtml/layout`: + - `customer_index_wishlist` +- `view/base/layout`: + - `catalog_product_prices` +- `view/frantend/layout`: + - `catalog_category_view` + - `catalog_product_view` + - `catalogsearch_advanced_result` + - `checkout_cart_index` + - `checkout_cart_item_renderers` + - `customer_account` + - `default` + - `wishlist_email_items` + - `wishlist_email_rss` + - `wishlist_index_configure` + - `wishlist_index_configure_type_bundle` + - `wishlist_index_configure_type_configurable` + - `wishlist_index_configure_type_downloadable` + - `wishlist_index_configure_type_grouped` + - `wishlist_index_configure_type_simple` + - `wishlist_index_index` + - `wishlist_index_share` + - `wishlist_shared_index.xml` + +For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). + +### UI components + +You can extend a customer form and widgets using the configuration files located in the directories +- `view/base/ui_component`: + - `customer_form` +- `view/frontend/ui_component`: + - `widget_recently_compared` + - `widget_recently_viewed` + +For information about a UI component in Magento 2, see [Overview of UI components](http://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). From 8584f85dbb74fd6b4a014d6f2199849446302d96 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Tue, 22 Dec 2020 14:19:07 +0530 Subject: [PATCH 059/242] Updated widget readme file --- app/code/Magento/Widget/README.md | 42 ++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Widget/README.md b/app/code/Magento/Widget/README.md index 4d70d3b6838e0..bac31207cc228 100644 --- a/app/code/Magento/Widget/README.md +++ b/app/code/Magento/Widget/README.md @@ -1 +1,41 @@ -The Widget module allows Magento application to be extended with custom widget blocks. \ No newline at end of file +# Magento_Widget module + +The **Magento_Widget** module allows Magento application to be extended with custom widget blocks. + +## Installation details + +Before installing this module, note that the **Magento_Widget** is dependent on the following modules: + +- Magento_Catalog +- Magento_Cms +- Magento_Store + +Before disabling or uninstalling this module, please consider the following dependencies: + +- Magento_CatalogWidget +- Magento_CurrencySymbol +- Magento_Newsletter + +Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Extensibility + +Extension developers can interact with the **Magento_Widget** module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Widget** module. + +### Layouts + +This module introduces the following layouts and layout handles in the directories: + +- `view/adminhtml/layout`: + - `adminhtml_widget_index` + - `adminhtml_widget_instance_block` + - `adminhtml_widget_instance_edit` + - `adminhtml_widget_instance_index` + - `adminhtml_widget_loadoptions` +- `view/frantend/layout`: + - `default` + - `print` + +For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). From ee667ff1e80c685b27bbe129bce1e4ff43d887bb Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Tue, 22 Dec 2020 14:24:54 +0530 Subject: [PATCH 060/242] Update README.md --- app/code/Magento/WishlistGraphQl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/WishlistGraphQl/README.md b/app/code/Magento/WishlistGraphQl/README.md index 3bab2a76bd5eb..43b455ad58b81 100644 --- a/app/code/Magento/WishlistGraphQl/README.md +++ b/app/code/Magento/WishlistGraphQl/README.md @@ -2,7 +2,7 @@ The **Magento_WishlistGraphQl** module adds, removes, and updates products on the wishlist. -The **Magento_WishlistGraphQl** module extends **Magento_GraphQl** and **Magento_Wishlist** modules. The module provides type and resolver information for GraphQL API. +The **Magento_WishlistGraphQl** module extends **Magento_GraphQl** and **Magento_Wishlist** modules. This module provides type and resolver information for GraphQL API. ## Installation details From af5765d2af52f59d364f7b2b0d035387ad8733bc Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Tue, 22 Dec 2020 14:34:02 +0530 Subject: [PATCH 061/242] Updated weee graphql module readme file --- app/code/Magento/WeeeGraphQl/README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/WeeeGraphQl/README.md b/app/code/Magento/WeeeGraphQl/README.md index b44771513d562..c80589a38af5c 100644 --- a/app/code/Magento/WeeeGraphQl/README.md +++ b/app/code/Magento/WeeeGraphQl/README.md @@ -1,4 +1,22 @@ -# WeeeGraphQl +# Magento_WeeeGraphQl module -**WeeeGraphQl** provides type information for the GraphQl module -to generate wee tax fields for catalog and product information endpoints. +The **Magento_WeeeGraphQl** module provides type information for the GraphQl module to generate wee tax fields for the catalog and product information endpoints. + +The **Magento_WeeeGraphQl** module extends **Magento_GraphQl** and **Magento_Weee** modules. This module provides type and resolver information for GraphQL API. + +## Installation details + +Before installing this module, note that the **Magento_WeeeGraphQl** is dependent on the following modules: + +- `Magento_CatalogGraphQl` +- `Magento_Store` +- `Magento_Tax` +- `Magento_Weee` + +For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Extensibility + +Extension developers can interact with the **Magento_WeeeGraphQl** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_WeeeGraphQl** module. From 4b007c23916f94a1dd4acd3ebcb7d75fa2daf47b Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Tue, 22 Dec 2020 13:28:26 +0200 Subject: [PATCH 062/242] added unit test; refactoring --- .../Block/Adminhtml/Order/Totals/TaxTest.php | 151 ++++++++++++------ 1 file changed, 101 insertions(+), 50 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php index 80563623e0050..222d26c30178a 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php @@ -5,9 +5,6 @@ */ declare(strict_types=1); -/** - * Test class for \Magento\Sales\Block\Adminhtml\Order\Totals\TaxTest - */ namespace Magento\Sales\Test\Unit\Block\Adminhtml\Order\Totals; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -16,46 +13,75 @@ use Magento\Sales\Model\Order\Creditmemo; use Magento\Sales\Model\Order\Invoice; use Magento\Tax\Helper\Data; +use Magento\Tax\Model\ResourceModel\Sales\Order\Tax\Collection; +use Magento\Tax\Model\Sales\Order\Tax as TaxModel; +use Magento\Tax\Model\Sales\Order\TaxFactory; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Test for \Magento\Sales\Block\Adminhtml\Order\Totals\Tax + */ class TaxTest extends TestCase { - /** @var MockObject|Tax */ + /** + * @var array + */ + private $calculatedData = [ + 'tax' => 'tax', + 'shipping_tax' => 'shipping_tax', + ]; + + /** + * @var MockObject|Tax + */ private $taxMock; + /** + * @var Data|MockObject + */ + private $taxHelperMock; + + /** + * @var TaxFactory|MockObject + */ + private $taxOrderFactory; + + /** + * @inheridoc + */ protected function setUp(): void { - $getCalculatedTax = [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ]; - $taxHelperMock = $this->getMockBuilder(Data::class) - ->setMethods(['getCalculatedTaxes']) + $this->taxHelperMock = $this->getMockBuilder(Data::class) + ->onlyMethods(['getCalculatedTaxes']) ->disableOriginalConstructor() ->getMock(); - $taxHelperMock->expects($this->any()) - ->method('getCalculatedTaxes') - ->willReturn($getCalculatedTax); + $this->taxOrderFactory = $this->createMock(TaxFactory::class); + + $arguments = $this->getModelArguments( + ['taxHelper' => $this->taxHelperMock, 'taxOrderFactory' => $this->taxOrderFactory] + ); $this->taxMock = $this->getMockBuilder(Tax::class) - ->setConstructorArgs($this->_getConstructArguments($taxHelperMock)) - ->setMethods(['getOrder', 'getSource']) + ->setConstructorArgs($arguments) + ->onlyMethods(['getOrder', 'getSource']) ->getMock(); } /** * Test method for getFullTaxInfo * - * @param Order $source - * @param array $getCalculatedTax - * @param array $getShippingTax + * @param Order|null $source * @param array $expectedResult + * @return void * * @dataProvider getFullTaxInfoDataProvider */ - public function testGetFullTaxInfo($source, $expectedResult) + public function testGetFullTaxInfo(?Order $source, array $expectedResult): void { + $this->taxHelperMock->expects($this->any()) + ->method('getCalculatedTaxes') + ->willReturn($this->calculatedData); $this->taxMock->expects($this->once()) ->method('getOrder') ->willReturn($source); @@ -69,13 +95,15 @@ public function testGetFullTaxInfo($source, $expectedResult) * * @param Invoice|Creditmemo $source * @param array $expectedResult + * @return void * * @dataProvider getCreditAndInvoiceFullTaxInfoDataProvider */ - public function testGetFullTaxInfoWithCreditAndInvoice( - $source, - $expectedResult - ) { + public function testGetFullTaxInfoWithCreditAndInvoice($source, array $expectedResult): void + { + $this->taxHelperMock->expects($this->any()) + ->method('getCalculatedTaxes') + ->willReturn($this->calculatedData); $this->taxMock->expects($this->once()) ->method('getSource') ->willReturn($source); @@ -84,19 +112,54 @@ public function testGetFullTaxInfoWithCreditAndInvoice( $this->assertSame($expectedResult, $actualResult); } + /** + * Test method for getFullTaxInfo when order doesn't have tax + * + * @return void + */ + public function testGetFullTaxInfoOrderWithoutTax(): void + { + $this->taxHelperMock->expects($this->once()) + ->method('getCalculatedTaxes') + ->willReturn(null); + + $orderMock = $this->createMock(Order::class); + $taxCollection = $this->createMock(Collection::class); + $taxCollection->expects($this->once()) + ->method('loadByOrder') + ->with($orderMock) + ->willReturnSelf(); + + $taxOrder = $this->createMock(TaxModel::class); + $taxOrder->expects($this->once()) + ->method('getCollection') + ->willReturn($taxCollection); + $this->taxOrderFactory->expects($this->once()) + ->method('create') + ->willReturn($taxOrder); + + $invoiceMock = $this->createMock(Invoice::class); + $this->taxMock->expects($this->once()) + ->method('getSource') + ->willReturn($invoiceMock); + $this->taxMock->expects($this->once()) + ->method('getOrder') + ->willReturn($orderMock); + + $this->assertNull($this->taxMock->getFullTaxInfo()); + } + /** * Provide the tax helper mock as a constructor argument * - * @param $taxHelperMock + * @param array $arguments * @return array */ - protected function _getConstructArguments($taxHelperMock) + private function getModelArguments(array $arguments): array { $objectManagerHelper = new ObjectManager($this); - return $objectManagerHelper->getConstructArguments( - Tax::class, - ['taxHelper' => $taxHelperMock] - ); + + return $objectManagerHelper->getConstructArguments(Tax::class, $arguments); } /** @@ -106,19 +169,15 @@ protected function _getConstructArguments($taxHelperMock) * * @return array */ - public function getFullTaxInfoDataProvider() + public function getFullTaxInfoDataProvider(): array { - $salesModelOrderMock = $this->getMockBuilder(Order::class) - ->disableOriginalConstructor() - ->getMock(); + $salesModelOrderMock = $this->createMock(Order::class); + return [ 'source is not an instance of \Magento\Sales\Model\Order' => [null, []], 'source is an instance of \Magento\Sales\Model\Order and has reasonable data' => [ $salesModelOrderMock, - [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ], + $this->calculatedData, ] ]; } @@ -130,22 +189,14 @@ public function getFullTaxInfoDataProvider() * * @return array */ - public function getCreditAndInvoiceFullTaxInfoDataProvider() + public function getCreditAndInvoiceFullTaxInfoDataProvider(): array { - $invoiceMock = $this->getMockBuilder(Invoice::class) - ->disableOriginalConstructor() - ->getMock(); - $creditMemoMock = $this->getMockBuilder(Creditmemo::class) - ->disableOriginalConstructor() - ->getMock(); + $invoiceMock = $this->createMock(Invoice::class); + $creditMemoMock = $this->createMock(Creditmemo::class); - $expected = [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ]; return [ - 'invoice' => [$invoiceMock, $expected], - 'creditMemo' => [$creditMemoMock, $expected] + 'invoice' => [$invoiceMock, $this->calculatedData], + 'creditMemo' => [$creditMemoMock, $this->calculatedData] ]; } } From 292c560070037f280d9953af7966af7d1acaf890 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 22 Dec 2020 13:54:39 +0200 Subject: [PATCH 063/242] =?UTF-8?q?MC-39809:=20A=20Product=20with=20Custom?= =?UTF-8?q?izable=20Option=20(File)=20can=20not=20be=20added=20by=20Admin?= =?UTF-8?q?=20from=20the=20=E2=80=9CShopping=20Cart=20section=20(=E2=80=9C?= =?UTF-8?q?Customer's=20Activities=E2=80=9D=20column)=20to=20Order?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Magento/Bundle/Test/Unit/Model/Product/TypeTest.php | 8 +++++++- .../Magento/Catalog/Model/Product/Type/AbstractType.php | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index b7041051591d8..9c4d4ce00b7c0 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -11,7 +11,6 @@ use Magento\Bundle\Model\Product\Type; use Magento\Bundle\Model\ResourceModel\BundleFactory; use Magento\Bundle\Model\ResourceModel\Option\Collection; -use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor; use Magento\Bundle\Model\ResourceModel\Selection\Collection as SelectionCollection; use Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory; use Magento\Bundle\Model\Selection; @@ -28,6 +27,7 @@ use Magento\CatalogInventory\Api\StockStateInterface; use Magento\CatalogInventory\Model\StockRegistry; use Magento\CatalogInventory\Model\StockState; +use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor; use Magento\Framework\DataObject; use Magento\Framework\EntityManager\EntityMetadataInterface; use Magento\Framework\EntityManager\MetadataPool; @@ -1548,6 +1548,10 @@ public function testPrepareForCartAdvancedSpecifyProductOptions() ->disableOriginalConstructor() ->getMock(); + $buyRequest->method('getOptions') + ->willReturn([333 => ['type' => 'image/jpeg']]); + $option->method('getId') + ->willReturn(333); $this->parentClass($group, $option, $buyRequest, $product); $product->expects($this->any()) @@ -1556,6 +1560,8 @@ public function testPrepareForCartAdvancedSpecifyProductOptions() $buyRequest->expects($this->once()) ->method('getBundleOption') ->willReturn([0, '', 'str']); + $group->expects($this->once()) + ->method('validateUserValue'); $result = $this->model->prepareForCartAdvanced($buyRequest, $product); $this->assertEquals('Please specify product option(s).', $result); diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index f90b097415661..19f6461d44b6a 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types=1); namespace Magento\Catalog\Model\Product\Type; @@ -605,7 +604,11 @@ protected function _prepareOptions(\Magento\Framework\DataObject $buyRequest, $p if ($product->getSkipCheckRequiredOption() !== true) { $group->validateUserValue($optionsFromRequest); } elseif ($optionsFromRequest !== null && isset($optionsFromRequest[$option->getId()])) { - $transport->options[$option->getId()] = $optionsFromRequest[$option->getId()]; + if (is_array($optionsFromRequest[$option->getId()])) { + $group->validateUserValue($optionsFromRequest); + } else { + $transport->options[$option->getId()] = $optionsFromRequest[$option->getId()]; + } } } catch (LocalizedException $e) { From 84b1ea0f3ff98c8e57049644fd1f456804738d0f Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Tue, 22 Dec 2020 14:43:23 +0200 Subject: [PATCH 064/242] fixed unit --- .../Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php index 222d26c30178a..b0c053a36de0f 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php @@ -129,6 +129,9 @@ public function testGetFullTaxInfoOrderWithoutTax(): void ->method('loadByOrder') ->with($orderMock) ->willReturnSelf(); + $taxCollection->expects($this->once()) + ->method('toArray') + ->willReturn(['items' => []]); $taxOrder = $this->createMock(TaxModel::class); $taxOrder->expects($this->once()) From cfa15e19f1d063e25b841178e33afe77606c5188 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Tue, 22 Dec 2020 15:16:59 +0200 Subject: [PATCH 065/242] refactored AdminCheckingCreditMemoTotalsTes --- ...dminCheckingCreditMemoUpdateTotalsTest.xml | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml index 37a4782ce2e73..03dd8b28a624f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCheckingCreditMemoUpdateTotalsTest.xml @@ -20,44 +20,61 @@ <group value="sales"/> </annotations> <before> - <!--Create product--> <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> - <!--Create customer--> + <createData entity="Simple_US_CA_Customer" stepKey="createCustomer"/> - <!--Login to admin page--> + + <createData entity="CustomerCart" stepKey="createCustomerCart"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + + <createData entity="CustomerCartItem" stepKey="addCartItem"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddress"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> + + <updateData createDataKey="createCustomerCart" entity="CustomerOrderPaymentMethod" stepKey="sendCustomerPaymentInformation"> + <requiredEntity createDataKey="createCustomerCart"/> + </updateData> + + <createData entity="Invoice" stepKey="invoiceOrderOne"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> <after> - <!--Delete simple product--> <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> - <!--Delete customer--> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <actionGroup ref="CreateOrderActionGroup" stepKey="createOrder"> - <argument name="product" value="$$createSimpleProduct$$"/> - <argument name="customer" value="$$createCustomer$$"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="createOrder"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="grabOrderId"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="startCreateInvoice"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="submitInvoice"/> + + <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="onOrderPage"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> + <grabTextFrom selector="{{AdminOrdersGridSection.orderIdByIncrementId($createCustomerCart.return$)}}" stepKey="getOrderId"/> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById"> + <argument name="orderId" value="{$getOrderId}"/> </actionGroup> - <grabFromCurrentUrl regex="~/order_id/(\d+)/~" stepKey="grabOrderId"/> - <!--Create invoice--> - <actionGroup ref="StartCreateInvoiceFromOrderPageActionGroup" stepKey="startCreateInvoice"/> - <!--Submit invoice--> - <actionGroup ref="SubmitInvoiceActionGroup" stepKey="submitInvoice"/> - <!--Create Credit Memo--> <actionGroup ref="StartToCreateCreditMemoActionGroup" stepKey="startToCreateCreditMemo"> - <argument name="orderId" value="{$grabOrderId}"/> + <argument name="orderId" value="{$getOrderId}"/> </actionGroup> <fillField selector="{{AdminCreditMemoTotalSection.refundShipping}}" userInput="0" stepKey="setRefundShipping"/> <actionGroup ref="UpdateCreditMemoTotalsActionGroup" stepKey="updateCreditMemoTotals"/> <actionGroup ref="SubmitCreditMemoActionGroup" stepKey="submitCreditMemo"/> - <!--Go to Credit Memo tab--> <click selector="{{AdminOrderDetailsOrderViewSection.creditMemos}}" stepKey="clickCreditMemosTab"/> <waitForPageLoad stepKey="waitForCreditMemosGridToLoad"/> - <!--Check refunded total --> <see selector="{{AdminOrderCreditMemosTabSection.gridRow('1')}}" userInput="$123" stepKey="seeCreditMemoInGrid"/> </test> </tests> From b162d05d3c2cb933ad8116debdb71d5ae3a5bb89 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Tue, 22 Dec 2020 18:09:24 +0200 Subject: [PATCH 066/242] magento/magento2#31251: [MFTF] Refactoring of Search actions on Storefront. --- ...roductWithRegularPriceInStockNotVisibleIndividuallyTest.xml | 1 - ...eProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 3 --- .../AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml | 1 - 3 files changed, 5 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index f36b76d0f8dcd..6cdc3da8d94a3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -89,7 +89,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="seeSelectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductNotVisibleIndividually.visibility}}" stepKey="seeSimpleProductVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSectionHeader"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index ee69bc5ced82b..807de2821fbc1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -38,9 +38,6 @@ <!-- Search default simple product in the grid --> <actionGroup ref="AdminClearFiltersActionGroup" stepKey="openProductCatalogPage"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterProductGrid"/> - <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="clickFirstRowToOpenDefaultSimpleProduct"> - <argument name="product" value="$$initialSimpleProduct$$"/> - </actionGroup><comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilProductIsOpened"/> <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilProductIsOpened"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 049d7fc0eaebe..4a7f6366617a8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -89,7 +89,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="selectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32503OutOfStock.urlKey}}" stepKey="seeUrlKey"/> From 7cf765776bec638224b4a3ea1c1bf51def4249d7 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Wed, 23 Dec 2020 15:15:05 +0530 Subject: [PATCH 067/242] Updated weee module readme file --- app/code/Magento/Weee/README.md | 113 ++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Weee/README.md b/app/code/Magento/Weee/README.md index ef433ec4c96f9..3ba049795b8c9 100644 --- a/app/code/Magento/Weee/README.md +++ b/app/code/Magento/Weee/README.md @@ -1,26 +1,99 @@ -# Overview -The Magento_Weee module enables the application of fees/fixed product taxes (FPT) on certain types of products, usually related to electronic devices and recycling. -Fixed product taxes can be used to setup a WEEE tax that is a fixed amount, rather than a percentage of the product price. FPT can be configured to be displayed at various places in Magento. Rules, amounts, and display options can be configured in the backend. This module extends the existing functionality of Magento_Tax. +# Magento_Weee module -The Magento_Weee module includes the following: +The **Magento_Weee** module enables the application of fees/fixed product taxes (FPT) on certain types of products, usually related to electronic devices and recycling. -* ability to add different number of fixed product taxes to product. They are treated as a product attribute; -* configuration of where WEEE appears (on category, product, sales, invoice, or credit memo pages) and whether FPT should be taxed; -* a new line item in the totals section. +Fixed product taxes can be used to setup a WEEE tax that is a fixed amount, rather than a percentage of the product price. FPT can be configured to be displayed at various places in Magento. Rules, amounts, and display options can be configured in the backend. -# System requirements -The Magento_Weee module does not have any specific system requirements. +This module extends the existing functionality of **Magento_Tax**. -## Install -Magento_Weee module can be installed automatically (using native Magento install mechanism) without any additional actions +The **Magento_Weee** module includes the following: -## Uninstall -Magento installation with existing products with FPT: -* Disable FPT on the backend -* Remove all products with FPT -* Remove all FPT attributes from attribute sets -* Delete all FPT attributes -* Remove module directory from the code base +- Ability to add different number of fixed product taxes to product. They are treated as a product attribute. +- Configuration of where WEEE appears (on category, product, sales, invoice, or credit memo pages) and whether FPT should be taxed. +- A new line item in the totals section. -New Magento installation: -* Can be removed without additional actions +## Installation details + +The **Magento_Weee** module can be installed automatically (using native Magento install mechanism) without any additional actions. + +Before installing this module, note that the **Magento_Weee** is dependent on the following modules: + +- Magento_Catalog +- Magento_Checkout +- Magento_Customer +- Magento_Quote +- Magento_Sales +- Magento_Store +- Magento_Tax + +Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Structure + +`Pricing/` - directory that contain tax adjustment. + +For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). + +## Extensibility + +Extension developers can interact with the **Magento_Weee** module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Weee** module. + +### Layouts + +This module introduces the following layouts and layout handles in the directories: + +- `view/adminhtml/layout`: + - `catalog_product_form` + - `sales_creditmemo_item_price` + - `sales_invoice_item_price` + - `sales_order_create_item_price` + - `sales_order_creditmemo_new` + - `sales_order_creditmemo_updateqty` + - `sales_order_creditmemo_view` + - `sales_order_invoice_new` + - `sales_order_invoice_updateqty` + - `sales_order_invoice_view` + - `sales_order_item_price` + - `sales_order_view` + +- `view/base/layout`: + - `catalog_product_prices` + +- `view/frantend/layout`: + - `checkout_cart_index` + - `checkout_index_index` + - `checkout_item_price_renderers` + - `default` + - `sales_email_item_price` + - `sales_email_order_creditmemo_items` + - `sales_email_order_invoice_items` + - `sales_email_order_items` + - `sales_guest_creditmemo` + - `sales_guest_invoice` + - `sales_guest_print` + - `sales_guest_printcreditmemo` + - `sales_guest_printinvoice` + - `sales_guest_view` + - `sales_order_creditmemo` + - `sales_order_invoice` + - `sales_order_item_price` + - `sales_order_print` + - `sales_order_printcreditmemo` + - `sales_order_printinvoice` + - `sales_order_view` + +For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). + +### UI components + +You can extend a customer form and widgets using the configuration files located in the directories + +- `view/adminhtml/ui_component`: + - `product_attribute_add_form` +- `view/frontend/ui_component`: + - `widget_recently_compared` + - `widget_recently_viewed` + +For information about a UI component in Magento 2, see [Overview of UI components](http://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). From db1be3fd789c37aaa4642f4c49e5fd48e84dc1c8 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Wed, 23 Dec 2020 15:31:07 +0530 Subject: [PATCH 068/242] Updated webapi security module readme file --- app/code/Magento/WebapiSecurity/README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/WebapiSecurity/README.md b/app/code/Magento/WebapiSecurity/README.md index ec5f84d1d14fa..954ec10d3dc60 100644 --- a/app/code/Magento/WebapiSecurity/README.md +++ b/app/code/Magento/WebapiSecurity/README.md @@ -1,6 +1,15 @@ -# WebapiSecurity +# Magento_WebapiSecurity module + +The **Magento_WebapiSecurity** module enables access management of some Web API resources. + +If checkbox enabled in backend through: `Stores -> Configuration -> Services -> Magento Web API -> Web Api Security` then the security of all the services outlined in `app/code/Magento/WebapiSecurity/etc/di.xml` would be loosened. You may modify this list to customize which services should follow this behavior. -**WebapiSecurity** enables access management of some Web API resources. -If checkbox is enabled in backend through: Stores -> Configuration -> Services -> Magento Web API -> Web Api Security -then the security of all of the services outlined in app/code/Magento/WebapiSecurity/etc/di.xml would be loosened. You may modify this list to customize which services should follow this behavior. By loosening the security, these services would allow access anonymously (by anyone). + +## Installation details + +Before installing this module, note that the **Magento_WebapiSecurity** is dependent on the following modules: + +- `Magento_Webapi` + +Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). From 6ef6f5789dcfa43b9507bfd64070dbb96f09f2f4 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 23 Dec 2020 12:04:59 +0200 Subject: [PATCH 069/242] added StorefrontGuestCheckoutProceedToPaymentStepActionGroup --- ...heckoutProceedToPaymentStepActionGroup.xml | 20 +++++++++++++++++++ ...sNotAffectedStartedCheckoutProcessTest.xml | 4 ++-- ...ckoutAsCustomerUsingDefaultAddressTest.xml | 4 ++-- ...utAsCustomerUsingNonDefaultAddressTest.xml | 4 ++-- ...tomerUsingNonExistentCustomerGroupTest.xml | 4 ++-- .../OnePageCheckoutUsingSignInLinkTest.xml | 4 ++-- ...OnePageCheckoutWithAllProductTypesTest.xml | 4 ++-- ...StorefrontCheckTaxAddingValidVATIdTest.xml | 4 ++-- ...dableProductLinkAfterPartialRefundTest.xml | 4 ++-- 9 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontGuestCheckoutProceedToPaymentStepActionGroup.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontGuestCheckoutProceedToPaymentStepActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontGuestCheckoutProceedToPaymentStepActionGroup.xml new file mode 100644 index 0000000000000..a55db2b92e9c3 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontGuestCheckoutProceedToPaymentStepActionGroup.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="StorefrontGuestCheckoutProceedToPaymentStepActionGroup"> + <annotations> + <description>Clicks next on Checkout Shipping step. Waits for Payment step</description> + </annotations> + + <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> + <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded" after="clickNext"/> + <seeInCurrentUrl url="{{CheckoutPage.url}}/#payment" stepKey="assertCheckoutPaymentUrl"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml index ffbd6152af80b..259934503ec0e 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/AdminCheckConfigsChangesIsNotAffectedStartedCheckoutProcessTest.xml @@ -67,8 +67,8 @@ <seeCheckboxIsChecked selector="{{CheckoutShippingMethodsSection.shippingMethodFreeShipping}}" stepKey="freeShippingMethodCheckboxIsChecked"/> <!-- Click Next button --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Payment step is opened --> <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml index 3d7f8e1dcfed4..b3c5174605575 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingDefaultAddressTest.xml @@ -69,8 +69,8 @@ <click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Select payment solution --> <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution" /> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml index 8fcb8211c4625..929943dcfde52 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonDefaultAddressTest.xml @@ -64,8 +64,8 @@ <click selector="{{CheckoutShippingSection.shipHereButton(DE_Address_Berlin_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <uncheckOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution"/> <!-- Change the address --> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest.xml index 6b1d3a7ba66aa..78c4d3301e746 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest.xml @@ -79,8 +79,8 @@ <click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Select payment solution --> <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution" /> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml index c7b1c441f1978..36ce5a87c9974 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutUsingSignInLinkTest.xml @@ -63,8 +63,8 @@ </actionGroup> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Select payment solution --> <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution" /> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 38e2203b45258..18f5b91348191 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -187,8 +187,8 @@ <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{CustomerAddressSimple.telephone}}" stepKey="fillPhone" /> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNextBtn"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Check order summary in checkout --> <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml index 5a75d5d272295..28ae33ff7f56b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCheckTaxAddingValidVATIdTest.xml @@ -87,8 +87,8 @@ <!--Proceed to checkout--> <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="GoToCheckoutFromMinicartActionGroup"/> <!-- Click next button to open payment section --> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Check order summary in checkout --> <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" time="30" stepKey="waitForPaymentSectionLoaded"/> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml index 2ced91731e4ba..47d89ca3b8700 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml @@ -70,8 +70,8 @@ <comment userInput="Adding the comment to replace waitForProceedToCheckout action for preserving Backward Compatibility" stepKey="waitForProceedToCheckout"/> <waitForElementVisible selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="waitForShipHereVisible"/> <click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/> - <click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/> - <waitForPageLoad stepKey="waitForShipmentPageLoad"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution"/> <waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/> <click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/> From 0b5401fa48ae61878f7a250ab589baf3c05b5070 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Wed, 23 Dec 2020 15:51:46 +0530 Subject: [PATCH 070/242] Updated webapi async module readme file --- app/code/Magento/WebapiAsync/README.md | 29 ++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/WebapiAsync/README.md b/app/code/Magento/WebapiAsync/README.md index ed57634e77caf..3d9a2b7b10967 100644 --- a/app/code/Magento/WebapiAsync/README.md +++ b/app/code/Magento/WebapiAsync/README.md @@ -1,3 +1,28 @@ -# WebapiAsync +# Magento_WebapiAsync module -**WebapiAsync** Extends Webapi extension and provide functional to process asynchronous requests. It handle asynchronous requests, schedule, publish and consum bulk operations from queue. +**Magento_WebapiAsync** module extends Webapi extension and provide functional to process asynchronous requests. + +**Magento_WebapiAsync** module handles asynchronous requests, schedule, publish and consume bulk operations from a queue. + +## Installation details + +Before installing this module, note that the **Magento_WebapiAsync** is dependent on the following modules: + +- Magento_AsynchronousOperations +- Magento_Customer +- Magento_User +- Magento_Webapi + +Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). + +## Structure + +`Code/` - the directory that contains Remote service reader configuration files. + +For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). + +## Extensibility + +Extension developers can interact with the Magento_WebapiAsync module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). + +[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WebapiAsync module. From 772b16fd9ace21f2b6145962d42e60ed9e245352 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Wed, 23 Dec 2020 12:57:04 +0200 Subject: [PATCH 071/242] magento/magento2#31251: [MFTF] Refactoring of Search actions on Storefront. --- .../Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml | 1 - ...oductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml | 1 - ...pleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 1 - ...mpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml | 1 - 4 files changed, 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index dbdf4dce301d3..a021bf2d7141e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -115,7 +115,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="seeSelectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelectToApplyChanges"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductTierPrice300InStock.urlKey}}" stepKey="seeUrlKey"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index c10cd19eef563..40d8fc0d288da 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -89,7 +89,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="selectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice245InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 807de2821fbc1..8b26272ac35fb 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -89,7 +89,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="selectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice32501InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index 9f4b4402fb94d..e79c1a549460f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -89,7 +89,6 @@ <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="selectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnAdvancedCategorySelect"/> <seeInField selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductRegularPrice325InStock.visibility}}" stepKey="seeVisibility"/> <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> From 275e42e42a51f3c04b2dafd4d17a8245e1a036cf Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Wed, 23 Dec 2020 13:39:28 +0200 Subject: [PATCH 072/242] MC-37385: Unexpected unchecking of "Append Comments" check-box --- .../Magento/Sales/Model/AdminOrder/Create.php | 7 ++-- .../Adminhtml/Order/Create/LoadBlockTest.php | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 5d621f1632837..a0e0dd9aeb2bd 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -1716,10 +1716,9 @@ public function importPostData($data) if (isset($data['comment'])) { $this->getQuote()->addData($data['comment']); - if (empty($data['comment']['customer_note_notify'])) { - $this->getQuote()->setCustomerNoteNotify(false); - } else { - $this->getQuote()->setCustomerNoteNotify(true); + if ($this->getIsValidate()) { + $notify = !empty($data['comment']['customer_note_notify']); + $this->getQuote()->setCustomerNoteNotify($notify); } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php index 529b491269643..3567a7e00764f 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php @@ -231,6 +231,40 @@ public function testAddProductToOrderFromWishList(): void $this->assertCount(1, $quoteItems); } + /** + * Check that customer notification is NOT disabled after comment is updated. + * + * @return void + * @magentoDataFixture Magento/Checkout/_files/quote_with_customer_without_address.php + */ + public function testUpdateCustomerNote(): void + { + $customerNote = 'Example Comment'; + $quoteId = $this->getQuoteByReservedOrderId->execute('test_order_with_customer_without_address')->getId(); + $this->session->setQuoteId($quoteId); + $params = [ + 'json' => false, + 'block' => 'totals', + 'as_js_varname' => false, + ]; + $post = $this->hydratePost([ + 'order' => [ + 'comment' => [ + CartInterface::KEY_CUSTOMER_NOTE => $customerNote + ], + ], + ]); + $this->dispatchWitParams($params, $post); + + $quote = $this->session->getQuote(); + $this->assertEquals($customerNote, $quote->getCustomerNote()); + $this->assertTrue((bool)$quote->getCustomerNoteNotify()); + + preg_match('/id="notify_customer"(?<attributes>.*?)\/>/s', $this->getResponse()->getBody(), $matches); + $this->assertArrayHasKey('attributes', $matches); + $this->assertStringContainsString('checked="checked"', $matches['attributes']); + } + /** * Check customer quotes * From e07d328c1f88e885ac6239d4689afcee09859394 Mon Sep 17 00:00:00 2001 From: tuna <ladiesman9x@gmail.com> Date: Fri, 18 Dec 2020 12:56:09 +0700 Subject: [PATCH 073/242] Update varnish 6 vcl config update --- app/code/Magento/PageCache/etc/varnish6.vcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/PageCache/etc/varnish6.vcl b/app/code/Magento/PageCache/etc/varnish6.vcl index bce89fe263573..cc381baaf313a 100644 --- a/app/code/Magento/PageCache/etc/varnish6.vcl +++ b/app/code/Magento/PageCache/etc/varnish6.vcl @@ -62,13 +62,13 @@ sub vcl_recv { return (pass); } - # Bypass shopping cart and checkout - if (req.url ~ "/checkout") { + # Bypass customer, shopping cart, checkout + if (req.url ~ "/customer" || req.url ~ "/checkout") { return (pass); } # Bypass health check requests - if (req.url ~ "/pub/health_check.php") { + if (req.url ~ "^/(pub/)?(health_check.php)$") { return (pass); } From 7889a6ffe566b7e13fa74877b0a7c3cf82cb9e45 Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Wed, 23 Dec 2020 17:56:20 +0200 Subject: [PATCH 074/242] Fix has been updated --- app/code/Magento/Customer/Block/Form/Register.php | 3 ++- app/code/Magento/Newsletter/Model/Config.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Customer/Block/Form/Register.php b/app/code/Magento/Customer/Block/Form/Register.php index d6d0d9c494c11..006deed601274 100644 --- a/app/code/Magento/Customer/Block/Form/Register.php +++ b/app/code/Magento/Customer/Block/Form/Register.php @@ -9,6 +9,7 @@ use Magento\Customer\Model\AccountManagement; use Magento\Framework\App\ObjectManager; use Magento\Newsletter\Model\Config; +use Magento\Store\Model\ScopeInterface; /** * Customer register form block @@ -184,7 +185,7 @@ public function getRegion() public function isNewsletterEnabled() { return $this->_moduleManager->isOutputEnabled('Magento_Newsletter') - && $this->newsLetterConfig->isActive(); + && $this->newsLetterConfig->isActive(ScopeInterface::SCOPE_STORE); } /** diff --git a/app/code/Magento/Newsletter/Model/Config.php b/app/code/Magento/Newsletter/Model/Config.php index eba0980e993b2..c469d35e74f72 100644 --- a/app/code/Magento/Newsletter/Model/Config.php +++ b/app/code/Magento/Newsletter/Model/Config.php @@ -41,7 +41,7 @@ public function __construct( * @param string $scopeType * @return bool */ - public function isActive(string $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_STORE): bool + public function isActive(string $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT): bool { return $this->scopeConfig->isSetFlag(self::XML_PATH_NEWSLETTER_ACTIVE, $scopeType); } From 1f04b0ad5871ddd04230636daa0f9d6d08a8b90c Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 23 Dec 2020 18:27:38 +0200 Subject: [PATCH 075/242] Updated with StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup --- .../Test/DeleteBundleDynamicProductFromShoppingCartTest.xml | 2 +- .../Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml | 2 +- .../Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml | 2 +- .../Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml | 2 +- ...orefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml | 2 +- .../Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml index 96a236336993f..a30f118bd6207 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml @@ -56,7 +56,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createBundleDynamicProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml index b64b59ef6109c..d1f452896c84f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml @@ -48,7 +48,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createFixedBundleProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 38e2203b45258..73a2e4757e954 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -159,7 +159,7 @@ <!-- Add Bundle Product to cart --> <amOnPage url="{{StorefrontProductPage.url($$createFixedBundleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToBundleProductPage"/> <waitForPageLoad stepKey="waitForFixedBundleProductPageLoad"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFixedBundleProductFromStorefrontProductPage"> <argument name="productName" value="$$createFixedBundleProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml index f16f577a4088c..3aa93d72571f9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml @@ -59,7 +59,7 @@ <amOnPage url="{{StorefrontProductPage.url($$createBundleDynamicProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add bundle product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createBundleDynamicProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml index ecbff39807f30..c81c6d36786eb 100644 --- a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml @@ -129,7 +129,7 @@ <argument name="product" value="$createBundleProduct$"/> </actionGroup> <waitForElementVisible selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="waitForCustomizeAndAddToCartButton"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <waitForPageLoad stepKey="waitForBundleProductPageLoad"/> <dontSeeElement selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="dontSeeButtonOnBundleProductPage"/> <!-- Grouped product --> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml index 59697bb6f5bdf..865852c10acfd 100644 --- a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml @@ -109,7 +109,7 @@ <!-- Bundle Product --> <amOnPage url="{{StorefrontProductPage.url($createBundleProduct.custom_attributes[url_key]$)}}" stepKey="openBundleProductPage"/> <waitForElementVisible selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="waitForCustomizeAndAddToCartButton"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <waitForElementVisible selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="waitForButtonOnBundleProductPage"/> <!-- Grouped product --> <amOnPage url="{{StorefrontProductPage.url($createGroupedProduct.custom_attributes[url_key]$)}}" stepKey="openGroupedProductPage"/> From 21c0bff1cf8e5ffcd73145574d9595d8625f53f3 Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Wed, 23 Dec 2020 19:11:33 +0200 Subject: [PATCH 076/242] Test has been added --- ...DisabledForStoreViewAtRegistrationTest.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml new file mode 100644 index 0000000000000..e49948e9d2aa8 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml @@ -0,0 +1,34 @@ +<?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="StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest"> + <annotations> + <features value="Newsletter"/> + <stories value="Disabled Newsletter Subscription for store View"/> + <title value="Disabled Newsletter Subscription for store View"/> + <description value="Option to subscribe should not be displayed at registration form if it is switched off for current store"/> + <severity value="AVERAGE"/> + <group value="newsletter"/> + <group value="configuration"/> + <testCaseId value="MC-*"/> + </annotations> + <before> + <magentoCLI command="config:set --scope=stores --scope-code=default newsletter/general/active 0" stepKey="disableSubscriptionForStore"/> + <magentoCLI command="cache:clean config" stepKey="cleanCache"/> + </before> + <after> + <magentoCLI command="config:set --scope=stores --scope-code=default newsletter/general/active 1" stepKey="enableSubscriptionForStore"/> + <magentoCLI command="cache:clean config" stepKey="cleanCacheAgain"/> + </after> + <actionGroup ref="StorefrontOpenCustomerAccountCreatePageActionGroup" stepKey="openCreateAccountPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <dontSeeElement selector="{{StorefrontCustomerCreateFormSection.signUpForNewsletter}}" stepKey="checkNoSubscriptionOption"/> + </test> +</tests> From 64d2fb97a832593ff0efdd6e32c0770d73b68140 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 23 Dec 2020 21:26:43 +0200 Subject: [PATCH 077/242] MC-39600: Create automated test for: "Change category/product url rewrite suffix in configurations" --- .../Catalog/Url/Rewrite/SuffixTest.php | 287 ++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php new file mode 100644 index 0000000000000..6553dffb04df6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php @@ -0,0 +1,287 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\System\Config\Backend\Catalog\Url\Rewrite; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; +use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; +use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\Framework\App\Cache\Type\Block; +use Magento\Framework\App\Cache\Type\Collection; +use Magento\Framework\App\Cache\TypeListInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\Storage\DbStorage; +use PHPUnit\Framework\TestCase; + +/** + * Class checks url suffix config save behaviour + * + * @see \Magento\Catalog\Model\System\Config\Backend\Catalog\Url\Rewrite\Suffix + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class SuffixTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Suffix */ + private $model; + + /** @var DbStorage */ + private $urlFinder; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var TypeListInterface */ + private $typeList; + + /** @var ScopeConfigInterface */ + private $scopeConfig; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var int */ + private $defaultStoreId; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(Suffix::class); + $this->urlFinder = $this->objectManager->get(DbStorage::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->typeList = $this->objectManager->get(TypeListInterface::class); + $this->scopeConfig = $this->objectManager->get(ScopeConfigInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->defaultStoreId = (int)$this->storeManager->getStore('default')->getId(); + } + + /** + * @return void + */ + public function testSaveWithError(): void + { + $this->expectException(LocalizedException::class); + $this->expectErrorMessage((string)__('Anchor symbol (#) is not supported in url rewrite suffix.')); + $this->model->setValue('.html#'); + $this->model->beforeSave(); + } + + /** + * @dataProvider wrongValuesProvider + * + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @param array $data + * @return void + */ + public function testSaveWithWrongData(array $data): void + { + $productId = (int)$this->productRepository->get('simple2')->getId(); + $this->model->addData($data); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + } + + /** + * @return array + */ + public function wrongValuesProvider(): array + { + return [ + 'with_wrong_path' => [ + ['path' => 'wrong_path', 'value' => 'some_test_value'], + ], + 'with_null_value' => [ + ['path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, 'value' => null], + ], + ]; + } + + /** + * @magentoDbIsolation disabled + * + * @magentoDataFixture Magento/Catalog/_files/product_multistore_different_short_description.php + * + * @return void + */ + public function testSaveInStoreScope(): void + { + $productId = $this->productRepository->get('simple-different-short-description')->getId(); + $newSuffix = 'some_test_value_for_store'; + $storeId = $this->storeManager->getStore('fixturestore')->getId(); + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + 'scope' => ScopeInterface::SCOPE_STORES, + 'scope_id' => $storeId, + ]); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + $this->assertRewrite( + $newSuffix, + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $storeId, + ] + ); + } + + /** + * @magentoDbIsolation disabled + * + * @magentoDataFixture Magento/Catalog/_files/product_two_websites.php + * + * @return void + */ + public function testSaveInWebsiteScope(): void + { + $productId = (int)$this->productRepository->get('simple-on-two-websites')->getId(); + $newSuffix = 'some_test_value_for_website'; + $website = $this->storeManager->getWebsite('test'); + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + 'scope' => ScopeInterface::SCOPE_WEBSITES, + 'scope_id' => $website->getId(), + ]); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + $this->assertRewrite( + $newSuffix, + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $website->getStoreIds(), + ] + ); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @magentoConfigFixture default_store catalog/seo/product_url_suffix .html_default + * + * @return void + */ + public function testSaveDefaultScopeWithOverrideStoreScope(): void + { + $productId = (int)$this->productRepository->get('simple2')->getId(); + $newSuffix = 'some_test_value'; + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + ]); + $this->model->afterSave(); + $this->assertRewrite( + '.html_default', + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category.php + * + * @return void + */ + public function testSaveCategorySuffix(): void + { + $this->model->addData(['path' => CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX, 'value' => null]); + $this->model->afterSave(); + $this->assertRewrite('.html', ['entity_type' => CategoryUrlRewriteGenerator::ENTITY_TYPE]); + $this->checkIsCacheInvalidated(); + } + + /** + * @return void + */ + public function testDeleteCategorySuffix(): void + { + $this->model->addData( + ['path' => CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX, 'value' => 'test_value'] + ); + $this->model->afterDeleteCommit(); + $this->checkIsCacheInvalidated(); + } + + /** + * Check that provided cache types are invalidated + * + * @param array $cacheTypes + * @return void + */ + private function checkIsCacheInvalidated( + array $cacheTypes = [Block::TYPE_IDENTIFIER, Collection::TYPE_IDENTIFIER] + ): void { + $types = $this->typeList->getTypes(); + + foreach ($cacheTypes as $type) { + $this->assertNotNull($types[$type]); + $this->assertEquals(0, $types[$type]->getStatus()); + } + } + + /** + * Assert url rewrite rewrite + * + * @param string $expectedSuffix + * @param array $data + * @return void + */ + private function assertRewrite(string $expectedSuffix, array $data) + { + $rewrite = $this->urlFinder->findOneByData($data); + $this->assertNotNull($rewrite); + $this->assertTrue( + substr($rewrite->getRequestPath(), -strlen($expectedSuffix)) === $expectedSuffix, + 'The url rewrite suffix does not match expected value' + ); + } +} From 198df361e52b3e53df9bdde642bdc30692a15ea3 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 23 Dec 2020 23:41:48 +0200 Subject: [PATCH 078/242] MC-24262: Async multistore webapi test fails with elasticsearch on CI --- .../Model/AsyncScheduleMultiStoreTest.php | 11 ++----- .../Store/_files/core_fixturestore.php | 33 +++++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php b/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php index fa9e45daf4438..b065f638cba0d 100644 --- a/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php +++ b/dev/tests/api-functional/testsuite/Magento/WebapiAsync/Model/AsyncScheduleMultiStoreTest.php @@ -95,17 +95,12 @@ protected function setUp(): void $this->objectManager = Bootstrap::getObjectManager(); $this->registry = $this->objectManager->get(Registry::class); - $params = array_merge_recursive( - Bootstrap::getInstance()->getAppInitParams(), - ['MAGE_DIRS' => ['cache' => ['path' => TESTS_TEMP_DIR . '/cache']]] - ); - $this->publisherConsumerController = $this->objectManager->create( PublisherConsumerController::class, [ 'consumers' => $this->consumers, 'logFilePath' => $logFilePath, - 'appInitParams' => $params, + 'appInitParams' => Bootstrap::getInstance()->getAppInitParams(), ] ); $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); @@ -129,13 +124,13 @@ protected function setUp(): void * @param string|null $storeCode * @return void */ - public function testAsyncScheduleBulkMultistore($storeCode): void + public function testAsyncScheduleBulkMultistore(?string $storeCode): void { $product = $this->getProductData(); $this->_markTestAsRestOnly(); /** @var Store $store */ - $store = $this->objectManager->create(Store::class); + $store = $this->objectManager->get(Store::class); $store->load(self::STORE_CODE_FROM_FIXTURE); $this->assertEquals( self::STORE_NAME_FROM_FIXTURE, diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/core_fixturestore.php b/dev/tests/integration/testsuite/Magento/Store/_files/core_fixturestore.php index a4a640a24de50..a60c672df6192 100644 --- a/dev/tests/integration/testsuite/Magento/Store/_files/core_fixturestore.php +++ b/dev/tests/integration/testsuite/Magento/Store/_files/core_fixturestore.php @@ -4,23 +4,28 @@ * See COPYING.txt for license details. */ +use Magento\Store\Model\ResourceModel\Store as StoreResource; +use Magento\Store\Model\StoreFactory; +use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; -/** @var \Magento\Store\Model\StoreManagerInterface $storeManager */ -$storeManager = Bootstrap::getObjectManager()->get(\Magento\Store\Model\StoreManagerInterface::class); - -/** @var \Magento\Store\Model\Store $store */ -$store = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class); +$objectManager = Bootstrap::getObjectManager(); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var StoreFactory $storeFactory */ +$storeFactory = $objectManager->get(StoreFactory::class); +/** @var StoreResource $storeResource */ +$storeResource = $objectManager->get(StoreResource::class); $storeCode = 'fixturestore'; -if (!$store->load($storeCode)->getId()) { - $store->setCode($storeCode) - ->setWebsiteId($storeManager->getWebsite()->getId()) - ->setGroupId($storeManager->getWebsite()->getDefaultGroupId()) - ->setName('Fixture Store') - ->setSortOrder(10) - ->setIsActive(1); - $store->save(); -} +$store = $storeFactory->create(); +$store->setCode($storeCode) + ->setWebsiteId($storeManager->getWebsite()->getId()) + ->setGroupId($storeManager->getWebsite()->getDefaultGroupId()) + ->setName('Fixture Store') + ->setSortOrder(10) + ->setIsActive(1); +$storeResource->save($store); +$storeManager->reinitStores(); //if test using this fixture relies on full text functionality it is required to explicitly perform re-indexation From ae96ab2081185de784b282408afa7d84a28c9635 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 24 Dec 2020 13:10:32 +0200 Subject: [PATCH 079/242] MC-40078: Create automated test for: "Create attribute without attribute code" --- .../Product/Attribute/RepositoryTest.php | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php new file mode 100644 index 0000000000000..94a5b52b03c5f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php @@ -0,0 +1,145 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Attribute; + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory; +use Magento\Catalog\Setup\CategorySetup; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Framework\Exception\InputException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks product attribute save behaviour. + * + * @see \Magento\Catalog\Model\Product\Attribute\Repository + * + * @magentoDbIsolation enabled + */ +class RepositoryTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Repository */ + private $repository; + + /** @var ProductAttributeInterfaceFactory */ + private $attributeFactory; + + /** @var ProductAttributeInterface */ + private $createdAttribute; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->repository = $this->objectManager->get(Repository::class); + $this->attributeFactory = $this->objectManager->get(ProductAttributeInterfaceFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + if ($this->createdAttribute instanceof ProductAttributeInterface) { + $this->repository->delete($this->createdAttribute); + } + + parent::tearDown(); + } + + /** + * @return void + */ + public function testSaveWithoutAttributeCode(): void + { + $this->createdAttribute = $this->saveAttributeWithData( + $this->hydrateData(['frontend_label' => 'Boolean Attribute']) + ); + $this->assertEquals('boolean_attribute', $this->createdAttribute->getAttributeCode()); + } + + /** + * @return void + */ + public function testSaveWithoutAttributeAndInvalidLabelCode(): void + { + $this->createdAttribute = $this->saveAttributeWithData($this->hydrateData(['frontend_label' => '/$&!/'])); + $this->assertStringStartsWith('attr_', $this->createdAttribute->getAttributeCode()); + } + + /** + * @dataProvider errorProvider + * + * @param string $fieldName + * @param string $fieldValue + * @return void + */ + public function testSaveWithInvalidCode(string $fieldName, string $fieldValue): void + { + $this->expectExceptionObject(InputException::invalidFieldValue($fieldName, $fieldValue)); + $this->createdAttribute = $this->saveAttributeWithData($this->hydrateData([$fieldName => $fieldValue])); + } + + /** + * @return array + */ + public function errorProvider():array + { + return [ + 'with_invalid_attribute_code' => [ + 'field_name' => 'attribute_code', + 'field_value' => '****', + ], + 'with_invalid_frontend_input' => [ + 'field_name' => 'frontend_input', + 'field_value' => 'invalid_input', + ], + ]; + } + + /** + * Save product attribute with data + * + * @param array $data + * @return ProductAttributeInterface + */ + private function saveAttributeWithData(array $data): ProductAttributeInterface + { + $attribute = $this->attributeFactory->create(); + $attribute->addData($data); + + return $this->repository->save($attribute); + } + + /** + * Hydrate data + * + * @param array $data + * @return array + */ + private function hydrateData(array $data): array + { + $defaultData = [ + 'entity_type_id' => CategorySetup::CATALOG_PRODUCT_ENTITY_TYPE_ID, + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'frontend_input' => 'boolean', + 'frontend_label' => 'default label', + ]; + + return array_merge($defaultData, $data); + } +} From 06ca9b27abc155a844511d1a02fba8af13ac6dc2 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 24 Dec 2020 13:14:29 +0200 Subject: [PATCH 080/242] MC-39600: Create automated test for: "Change category/product url rewrite suffix in configurations" --- .../System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php index 6553dffb04df6..9979e8cd6ea68 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php @@ -275,7 +275,7 @@ private function checkIsCacheInvalidated( * @param array $data * @return void */ - private function assertRewrite(string $expectedSuffix, array $data) + private function assertRewrite(string $expectedSuffix, array $data): void { $rewrite = $this->urlFinder->findOneByData($data); $this->assertNotNull($rewrite); From 200831eb418d984c00180260576b2ab5a4165290 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 24 Dec 2020 13:36:35 +0200 Subject: [PATCH 081/242] added AdminClearFiltersOnGridActionGroup --- .../AdminClearFiltersOnGridActionGroup.xml | 19 +++++++++++++++++++ ...UpdateTopCategoryUrlWithNoRedirectTest.xml | 4 ++-- ...inUpdateTopCategoryUrlWithRedirectTest.xml | 4 ++-- .../Test/AdminEmailTemplatePreviewTest.xml | 2 +- ...EmailTemplatePreviewWithDirectivesTest.xml | 2 +- .../Test/AdminCreateDefaultsTaxRuleTest.xml | 2 +- .../AdminCreateTaxRateAllPostCodesTest.xml | 4 ++-- .../Test/AdminCreateTaxRateLargeRateTest.xml | 2 +- ...AdminCreateTaxRateSpecificPostcodeTest.xml | 2 +- ...dminCreateTaxRateWiderZipCodeRangeTest.xml | 2 +- .../AdminCreateTaxRateZipCodeRangeTest.xml | 2 +- ...RuleWithCustomerAndProductTaxClassTest.xml | 2 +- ...xRateAndCustomerAndProductTaxClassTest.xml | 2 +- ...TaxRuleWithNewTaxClassesAndTaxRateTest.xml | 2 +- .../AdminCreateTaxRuleWithZipRangeTest.xml | 2 +- .../Test/Mftf/Test/AdminDeleteTaxRuleTest.xml | 4 ++-- .../Test/AdminUpdateDefaultTaxRuleTest.xml | 4 ++-- ...dminUpdateTaxRuleWithCustomClassesTest.xml | 4 ++-- ...AdminUpdateTaxRuleWithFixedZipUtahTest.xml | 4 ++-- .../Mftf/Test/DeleteTaxRateEntityTest.xml | 2 +- .../Mftf/Test/Update01TaxRateEntityTest.xml | 4 ++-- .../Mftf/Test/Update100TaxRateEntityTest.xml | 4 ++-- .../Mftf/Test/Update1299TaxRateEntityTest.xml | 4 ++-- .../Test/UpdateAnyRegionTaxRateEntityTest.xml | 4 ++-- .../Test/UpdateDecimalTaxRateEntityTest.xml | 4 ++-- .../Test/UpdateLargeTaxRateEntityTest.xml | 4 ++-- 26 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml new file mode 100644 index 0000000000000..fd9e210021996 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.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="AdminClearFiltersOnGridActionGroup"> + <annotations> + <description>Click the Clear filters on the grid.</description> + </annotations> + + <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters"/> + <waitForPageLoad stepKey="waitForPageLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml index 616c38e326a62..08c3ba49d0649 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml @@ -79,8 +79,8 @@ <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updatedurl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's old URL path doesn't show redirect path--> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickOnResetButton1"/> - <waitForPageLoad stepKey="waitForPageToLoad3"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickOnResetButton1"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoad3"/> <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="{{Three_nested_categories.name_lwr}}" stepKey="fillOldUrlInRedirectPathFilter"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml index 9d4bc5f184c9c..49d2c24f26bae 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml @@ -77,8 +77,8 @@ <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's Redirect path, Target Path and Redirect type for old URL --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickOnResetButton1"/> - <waitForPageLoad stepKey="waitForPageToLoad4"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickOnResetButton1"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoad4"/> <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$$createThreeLevelNestedCategories.name$$" stepKey="fillOldUrlInRedirectPathFilter"/> <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickOrderApplyFilters1"/> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml index 22e70b72e5401..16ddacf0e04ed 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml @@ -29,7 +29,7 @@ <after> <!--Delete created Template--> <actionGroup ref="DeleteEmailTemplateActionGroup" stepKey="deleteTemplate"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clearFilters"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clearFilters"/> <!--Logout from Admin Area--> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml index 7683591e8f37f..06da55e2cac49 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml @@ -29,7 +29,7 @@ <after> <!--Delete created Template--> <actionGroup ref="DeleteEmailTemplateActionGroup" stepKey="deleteTemplate"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clearFilters"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clearFilters"/> <!--Logout from Admin Area--> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml index 5e7ce53a3a3fc..62d32fba70496 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml @@ -42,7 +42,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="assertTaxRuleSuccessMessage" /> <!-- Verify we see created tax rule with defaults(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch" /> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml index ceb04a9c42e66..3cbd47d4f3a0f 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml @@ -43,7 +43,7 @@ <!-- Verify the tax rate grid page shows the tax rate we just created --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillNameFilter"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="Australia" stepKey="fillCountryFilter"/> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="*" stepKey="fillPostCodeFilter"/> @@ -54,7 +54,7 @@ <!-- Go to the tax rate edit page for our new tax rate --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex3"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillNameFilter2"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml index 7497b950a8c0e..2fb3a4cb9935c 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for large postcodes and verify we see expected values on the tax rate grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="France" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="*" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml index da89ad3e9337c..3193ed5bb7391 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Verify the tax rate grid page shows the specific postcode we just created --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="Canada" stepKey="fillCountryFilter"/> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="180" stepKey="fillPostCodeFilter"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml index da30157d94182..3b2c9f0a58fa5 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for zipCodeRange and verify we see expected values on the tax rate grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="United Kingdom" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="1-7800935" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml index 93e0f6514e83b..827b2fcbac2b3 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml @@ -46,7 +46,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for zipCodeRange and verify we see expected values on the tax rate grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="United States" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="90001-96162" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml index f1a48af741cd6..160f9c008a5d2 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml @@ -68,7 +68,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with customer and product class(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml index de7a0fb2d9144..9dabe5a317644 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml @@ -63,7 +63,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with new and existing tax rate, customer tax class, product tax class(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml index 4798ec60ab898..38bef10da1af2 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml @@ -67,7 +67,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with new tax classes and tax rate(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml index a08c878ba2063..5dd233a66d228 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml @@ -65,7 +65,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with zip range(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml index 37b90300aad28..95572488819ff 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml @@ -31,7 +31,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -46,7 +46,7 @@ <!-- Confirm Deleted Tax Rule(from the above step) on the tax rule grid page --> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <see selector="{{AdminTaxRuleGridSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeAssertTaxRuleNotFound"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml index fd445326976e4..ff45a8f324326 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml @@ -39,7 +39,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -64,7 +64,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with default(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml index 3a5607ea598ca..8a14a84741faf 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml @@ -40,7 +40,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -62,7 +62,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with default(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml index fa42ce5ddafa3..94672b35c5aba 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml @@ -44,7 +44,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -66,7 +66,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with fixed zip Utah(from the above step) on the tax rule grid page --> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml index 751989497d10e..c9f38a38b81e8 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml @@ -36,7 +36,7 @@ <!-- Confirm Deleted TaxIdentifier(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRate.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <see selector="{{AdminTaxRateGridSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeSuccess"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml index ff75b1e95646a..549b7d01375c2 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -45,7 +45,7 @@ <!-- Verify we see updated 0.1 tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateFrance.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml index ebfa1288b59dd..b1f7611bd36ea 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -44,7 +44,7 @@ <!-- Verify we see updated TaxIdentifier(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateUS.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml index ed1c126930df8..343d912941e6c 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax identifier on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode1"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -45,7 +45,7 @@ <!-- Verify we see updated tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateUK.code}}" stepKey="fillTaxIdentifierField2"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml index 7a2f0664d7757..4ccc77c940438 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -44,7 +44,7 @@ <!-- Verify we see updated any region tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateCanada.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml index 03aba8da8ae19..00ac9e045a5ad 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -46,7 +46,7 @@ <!-- Verify we see updated tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRateWithZipRange.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml index 37b8bb8d95618..79a5b4349f69d 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -43,7 +43,7 @@ <!-- Verify we see updated large tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <click selector="{{AdminDataGridHeaderSection.clearFilters}}" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRateWithLargeRate.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> From 958af2bef627d164c29165be3ad5f9a2c0f2082b Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Thu, 24 Dec 2020 16:31:43 +0200 Subject: [PATCH 082/242] magento/magento2#31251: [MFTF] Refactoring of Search actions on Storefront. --- .../Test/AdminCreateProductAttributeFromProductPageTest.xml | 4 ++-- ...oductWithRegularPriceInStockNotVisibleIndividuallyTest.xml | 4 ++-- ...ctWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml | 2 +- ...ProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 2 +- ...roductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml index 3cf13bbd2f602..100d4bdef5f48 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateProductAttributeFromProductPageTest.xml @@ -55,7 +55,7 @@ <fillField selector="{{AdminProductFormSection.productQuantity}}" userInput="100" stepKey="fillProductQty"/> <actionGroup ref="AdminSetStockStatusActionGroup" stepKey="selectStockStatus"> <argument name="stockStatus" value="In Stock"/> - </actionGroup> + </actionGroup> <!-- Create New Product Attribute --> <click selector="{{AdminProductFormSection.addAttributeBtn}}" stepKey="clickOnAddAttribute"/> @@ -133,7 +133,7 @@ </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSearchTextBoxButton"/> - <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchResultToLoad"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearch"/> <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductNameInCategoryPage"> <argument name="productName" value="{{SimpleProduct.name}}"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index 6cdc3da8d94a3..b5c04d2ba11f0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -57,7 +57,7 @@ <fillField selector="{{AdminProductFormSection.searchCategory}}" userInput="$$categoryEntity.name$$" stepKey="fillSearchCategory"/> <waitForPageLoad stepKey="waitForCategory2"/> <click selector="{{AdminProductFormSection.selectCategory($$categoryEntity.name$$)}}" stepKey="clickOnCategory"/> - <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickDoneOnCategorySelect"/> + <actionGroup ref="AdminSubmitCategoriesPopupActionGroup" stepKey="clickOnDoneAdvancedCategorySelect"/> <selectOption selector="{{AdminProductFormSection.visibility}}" userInput="{{simpleProductNotVisibleIndividually.visibility}}" stepKey="selectVisibility"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection"/> <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductNotVisibleIndividually.urlKey}}" stepKey="fillSimpleProductUrlKey"/> @@ -95,7 +95,7 @@ <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductNotVisibleIndividually.urlKey}}" stepKey="seeSimpleProductUrlKey"/> <!--Verify customer don't see updated simple product link on magento storefront page --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductNotVisibleIndividually.urlKey)}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> + <amOnPage url="{{StorefrontProductPage.url(simpleProductNotVisibleIndividually.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> <argument name="phrase" value="{{simpleProductNotVisibleIndividually.sku}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 40d8fc0d288da..0d0391ea5a873 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -124,7 +124,7 @@ </assertEquals> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> - <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="fillSimpleProductSkuInSearchTextBox"/> + <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> <argument name="phrase" value="{{simpleProductRegularPrice245InStock.sku}}"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 8b26272ac35fb..76a768c1b2d21 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -126,7 +126,7 @@ <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32501InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBo"> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> <argument name="phrase" value="{{simpleProductRegularPrice32501InStock.sku}}"/> </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml index cda4e092a444f..39ecb8c3bfd01 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockVisibleInCategoryOnlyTest.xml @@ -116,7 +116,7 @@ <!-- Verify customer don't see updated virtual product link on storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(updateVirtualProductRegularPrice.urlKey)}}" stepKey="goToProductPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductSkuOnStorefrontPagee"> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillVirtualProductSkuOnStorefrontPage"> <argument name="phrase" value="{{updateVirtualProductRegularPrice.sku}}"/> </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> From 772d1785ca60fd9a3c2c36f9779b14a01e3bc300 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 24 Dec 2020 16:49:14 +0200 Subject: [PATCH 083/242] MC-36683: [Cloud]Generating companies... Could not save company --- setup/performance-toolkit/config/di.xml | 2 + .../Mail/Template/TransportBuilderMock.php | 28 ++++++++++++ .../Framework/Mail/TransportInterfaceMock.php | 45 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php create mode 100644 setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php diff --git a/setup/performance-toolkit/config/di.xml b/setup/performance-toolkit/config/di.xml index 0b1175b0cd94c..a293edcb216af 100644 --- a/setup/performance-toolkit/config/di.xml +++ b/setup/performance-toolkit/config/di.xml @@ -6,4 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <preference for="Magento\Framework\Mail\TransportInterface" type="Magento\Setup\Framework\Mail\TransportInterfaceMock"/> + <preference for="Magento\Framework\Mail\Template\TransportBuilder" type="Magento\Setup\Framework\Mail\Template\TransportBuilderMock"/> </config> diff --git a/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php b/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php new file mode 100644 index 0000000000000..2791487c37ba5 --- /dev/null +++ b/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Setup\Framework\Mail\Template; + +use Magento\Framework\Mail\Template\TransportBuilder; +use Magento\Setup\Framework\Mail\TransportInterfaceMock; + +/** + * Mock for mail template transport builder. + */ +class TransportBuilderMock extends TransportBuilder +{ + /** + * @inheritDoc + */ + public function getTransport() + { + $this->prepareMessage(); + $this->reset(); + + return new TransportInterfaceMock($this->message); + } +} diff --git a/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php b/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php new file mode 100644 index 0000000000000..64abddc053504 --- /dev/null +++ b/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Setup\Framework\Mail; + +use Magento\Framework\Mail\EmailMessageInterface; +use Magento\Framework\Mail\TransportInterface; + +/** + * Mock for mail transport. + */ +class TransportInterfaceMock implements TransportInterface +{ + /** + * @var EmailMessageInterface|null + */ + private $message; + + /** + * @param EmailMessageInterface|null $message + */ + public function __construct($message = null) + { + $this->message = $message; + } + + /** + * @inheritDoc + */ + public function sendMessage() + { + } + + /** + * @inheritDoc + */ + public function getMessage() + { + return $this->message; + } +} From fe4b27b89a4e4527a34d4fceb7d690ca1b51c3e6 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 24 Dec 2020 17:04:17 +0200 Subject: [PATCH 084/242] MC-40078: Create automated test for: "Create attribute without attribute code" --- .../Catalog/Model/Product/Attribute/RepositoryTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php index 94a5b52b03c5f..7430ebf72f8fb 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Catalog\Setup\CategorySetup; use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; use Magento\Framework\Exception\InputException; @@ -28,7 +29,7 @@ class RepositoryTest extends TestCase /** @var ObjectManagerInterface */ private $objectManager; - /** @var Repository */ + /** @var ProductAttributeRepositoryInterface */ private $repository; /** @var ProductAttributeInterfaceFactory */ @@ -45,7 +46,7 @@ protected function setUp(): void parent::setUp(); $this->objectManager = Bootstrap::getObjectManager(); - $this->repository = $this->objectManager->get(Repository::class); + $this->repository = $this->objectManager->get(ProductAttributeRepositoryInterface::class); $this->attributeFactory = $this->objectManager->get(ProductAttributeInterfaceFactory::class); } @@ -97,7 +98,7 @@ public function testSaveWithInvalidCode(string $fieldName, string $fieldValue): /** * @return array */ - public function errorProvider():array + public function errorProvider(): array { return [ 'with_invalid_attribute_code' => [ From 2c80277103eab5b9c497d6c6ef32e6103ef70b32 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 24 Dec 2020 18:19:13 +0200 Subject: [PATCH 085/242] MC-39711: Create automated test for: "Filter products in admin grid" --- .../AddQuantityFilterToCollectionTest.php | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php new file mode 100644 index 0000000000000..f0d87f06514f1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Ui\DataProvider\Product; + +use Magento\Framework\App\RequestInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks that the product quantity filter is working correctly + * + * @magentoAppArea adminhtml + */ +class AddQuantityFilterToCollectionTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var UiComponentFactory */ + private $componentFactory; + + /** @var RequestInterface */ + private $request; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->request = $this->objectManager->get(RequestInterface::class); + $this->componentFactory = $this->objectManager->get(UiComponentFactory::class); + } + + /** + * @dataProvider quantityFilterProvider + * @magentoDataFixture Magento/Catalog/_files/multiple_products.php + * @param array $filter + * @param array $expectedProducts + * @return void + */ + public function testQuantityFilter(array $filter, array $expectedProducts): void + { + $this->request->setParams([ContextInterface::FILTER_VAR => $filter]); + $dataProviderData = $this->getComponentProvidedData('product_listing'); + $actualProducts = array_column($dataProviderData['items'], 'sku'); + $this->assertEquals($expectedProducts, $actualProducts, 'Expected products do not match actual products!'); + } + + /** + * Data provider for testQuantityFilter + * + * @return array + */ + public function quantityFilterProvider(): array + { + return [ + 'from' => [ + 'filter' => [ + 'qty' => [ + 'from' => 100, + ], + ], + 'expected_products' => [ + 'simple1', + 'simple3', + ], + ], + 'to' => [ + 'filter' => [ + 'qty' => [ + 'to' => 100, + ], + ], + 'expected_products' => [ + 'simple1', + 'simple2', + ], + ], + 'both' => [ + 'filter' => [ + 'qty' => [ + 'from' => 60, + 'to' => 130, + ], + ], + 'expected_products' => [ + 'simple1', + ], + ], + ]; + } + + /** + * Call prepare method in the child components + * + * @param UiComponentInterface $component + * @return void + */ + private function prepareChildComponents(UiComponentInterface $component): void + { + foreach ($component->getChildComponents() as $child) { + $this->prepareChildComponents($child); + } + + $component->prepare(); + } + + /** + * Get component provided data + * + * @param string $namespace + * @return array + */ + private function getComponentProvidedData(string $namespace): array + { + $component = $this->componentFactory->create($namespace); + $this->prepareChildComponents($component); + + return $component->getContext()->getDataProvider()->getData(); + } +} From 57e23c6fdcc2c4232f72fe2d5361c82b47a7a7d4 Mon Sep 17 00:00:00 2001 From: Sergiy Vasiutynskyi <s.vasiutynskyi@atwix.com> Date: Fri, 25 Dec 2020 13:32:35 +0200 Subject: [PATCH 086/242] Updated value of CliIndexerReindexActionGroup action for failed test --- .../Test/ProductAvailableAfterEnablingSubCategoriesTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index b5980cf977791..f7e35f1503a12 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -50,7 +50,7 @@ <!--Run re-index task--> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value="cataloginventory_stock"/> + <argument name="indices" value="cataloginventory_stock catalog_product_price"/> </actionGroup> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomepage"/> From 9ca51cd1f92bc058a112f02fe85f6f4838261ba2 Mon Sep 17 00:00:00 2001 From: Sergiy Vasiutynskyi <s.vasiutynskyi@atwix.com> Date: Fri, 25 Dec 2020 17:03:44 +0200 Subject: [PATCH 087/242] Updated value of CliIndexerReindexActionGroup action for failed test --- .../Test/ProductAvailableAfterEnablingSubCategoriesTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index f7e35f1503a12..654dc727b24ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -50,7 +50,7 @@ <!--Run re-index task--> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value="cataloginventory_stock catalog_product_price"/> + <argument name="indices" value="catalog_product_price"/> </actionGroup> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomepage"/> From 01a656ff2a318edbcc179231e31ad9b3c8565066 Mon Sep 17 00:00:00 2001 From: CJ <cperumal@ztech.io> Date: Mon, 28 Dec 2020 12:24:25 +0530 Subject: [PATCH 088/242] Chaged http to https --- app/code/Magento/WebapiAsync/README.md | 6 +++--- app/code/Magento/Weee/README.md | 10 +++++----- app/code/Magento/WeeeGraphQl/README.md | 2 +- app/code/Magento/Widget/README.md | 6 +++--- app/code/Magento/Wishlist/README.md | 10 +++++----- app/code/Magento/WishlistGraphQl/README.md | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/WebapiAsync/README.md b/app/code/Magento/WebapiAsync/README.md index 3d9a2b7b10967..36b092c938fa3 100644 --- a/app/code/Magento/WebapiAsync/README.md +++ b/app/code/Magento/WebapiAsync/README.md @@ -19,10 +19,10 @@ Please find here [how to enable or disable modules in Magento 2](https://devdocs `Code/` - the directory that contains Remote service reader configuration files. -For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility -Extension developers can interact with the Magento_WebapiAsync module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the Magento_WebapiAsync module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WebapiAsync module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WebapiAsync module. diff --git a/app/code/Magento/Weee/README.md b/app/code/Magento/Weee/README.md index 3ba049795b8c9..0e846694523a9 100644 --- a/app/code/Magento/Weee/README.md +++ b/app/code/Magento/Weee/README.md @@ -32,13 +32,13 @@ Please find here [how to enable or disable modules in Magento 2](https://devdocs `Pricing/` - directory that contain tax adjustment. -For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility -Extension developers can interact with the **Magento_Weee** module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the **Magento_Weee** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Weee** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Weee** module. ### Layouts @@ -84,7 +84,7 @@ This module introduces the following layouts and layout handles in the directori - `sales_order_printinvoice` - `sales_order_view` -For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). ### UI components @@ -96,4 +96,4 @@ You can extend a customer form and widgets using the configuration files located - `widget_recently_compared` - `widget_recently_viewed` -For information about a UI component in Magento 2, see [Overview of UI components](http://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). +For information about a UI component in Magento 2, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). diff --git a/app/code/Magento/WeeeGraphQl/README.md b/app/code/Magento/WeeeGraphQl/README.md index c80589a38af5c..81ee1236f00a2 100644 --- a/app/code/Magento/WeeeGraphQl/README.md +++ b/app/code/Magento/WeeeGraphQl/README.md @@ -19,4 +19,4 @@ For information about enabling or disabling a module in Magento 2, see [Enable o Extension developers can interact with the **Magento_WeeeGraphQl** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_WeeeGraphQl** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_WeeeGraphQl** module. diff --git a/app/code/Magento/Widget/README.md b/app/code/Magento/Widget/README.md index bac31207cc228..8c06ee4c30fa9 100644 --- a/app/code/Magento/Widget/README.md +++ b/app/code/Magento/Widget/README.md @@ -20,9 +20,9 @@ Please find here [how to enable or disable modules in Magento 2](https://devdocs ## Extensibility -Extension developers can interact with the **Magento_Widget** module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the **Magento_Widget** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Widget** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Widget** module. ### Layouts @@ -38,4 +38,4 @@ This module introduces the following layouts and layout handles in the directori - `default` - `print` -For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). diff --git a/app/code/Magento/Wishlist/README.md b/app/code/Magento/Wishlist/README.md index 67fbef6771cba..c9ac4960c2180 100644 --- a/app/code/Magento/Wishlist/README.md +++ b/app/code/Magento/Wishlist/README.md @@ -26,9 +26,9 @@ For information about a typical file structure of a module in Magento 2, see [Mo ## Extensibility -Extension developers can interact with the Magento_Wishlist module. For more information about the Magento extension mechanism, see [Magento plug-ins](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the Magento_Wishlist module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_Wishlist module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_Wishlist module. ### Events @@ -56,7 +56,7 @@ The module dispatches the following events: - `product` is a product object (`\Magento\Catalog\Api\Data\ProductInterface` class). - `item` is an item object (`\Magento\Wishlist\Model\Item` class). -For information about the event system in Magento 2, see [Events and observers](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/events-and-observers.html#events). +For information about the event system in Magento 2, see [Events and observers](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/events-and-observers.html#events). ### Layouts @@ -86,7 +86,7 @@ This module introduces the following layouts and layout handles in the directori - `wishlist_index_share` - `wishlist_shared_index.xml` -For more information about a layout in Magento 2, see the [Layout documentation](http://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). ### UI components @@ -97,4 +97,4 @@ You can extend a customer form and widgets using the configuration files located - `widget_recently_compared` - `widget_recently_viewed` -For information about a UI component in Magento 2, see [Overview of UI components](http://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). +For information about a UI component in Magento 2, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). diff --git a/app/code/Magento/WishlistGraphQl/README.md b/app/code/Magento/WishlistGraphQl/README.md index 43b455ad58b81..7f2ba3dfa44b4 100644 --- a/app/code/Magento/WishlistGraphQl/README.md +++ b/app/code/Magento/WishlistGraphQl/README.md @@ -25,7 +25,7 @@ For information about enabling or disabling a module in Magento 2, see [Enable o Extension developers can interact with the Magento_WishlistGraphQl module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WishlistGraphQl module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WishlistGraphQl module. ## Additional information From ed701258ce3d061899cf8d1e7143b67ca77830f9 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 28 Dec 2020 12:26:35 +0530 Subject: [PATCH 089/242] Update README.md --- app/code/Magento/Wishlist/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/README.md b/app/code/Magento/Wishlist/README.md index c9ac4960c2180..66e0d90d5f0b2 100644 --- a/app/code/Magento/Wishlist/README.md +++ b/app/code/Magento/Wishlist/README.md @@ -22,7 +22,7 @@ Please find here [how to enable or disable modules in Magento 2](https://devdocs `Pricing/` - the directory that contain solutions for configurable and downloadable product price. -For information about a typical file structure of a module in Magento 2, see [Module file structure](http://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility From f543cedd3c02ee717e23c22b833e2717566217a6 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 28 Dec 2020 10:55:29 +0200 Subject: [PATCH 090/242] MC-39575: Create automated test for "Apply visual swatch attribute filter on layered navigation" --- .../Configurable/Listing/ConfigurableTest.php | 115 ++++++++++++++++++ .../configurable_product_with_images.php | 41 +++++++ ...figurable_product_with_images_rollback.php | 15 +++ 3 files changed, 171 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php new file mode 100644 index 0000000000000..f2d254af85c94 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php @@ -0,0 +1,115 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Block\Product\Renderer\Configurable\Listing; + +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Module\Manager; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Swatches\Block\Product\Renderer\Listing\Configurable; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for configurable products options block with swatch attribute. + * + * @magentoDbIsolation enabled + * @magentoAppArea frontend + */ +class ConfigurableTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var SerializerInterface + */ + private $serializer; + + /** + * @var Configurable + */ + private $block; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var ProductAttributeRepositoryInterface + */ + private $productAttributeRepository; + + /** + * @var RequestInterface + */ + private $request; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass(): void + { + $objectManager = Bootstrap::getObjectManager(); + /** @var Manager $moduleManager */ + $moduleManager = $objectManager->get(Manager::class); + if (!$moduleManager->isEnabled('Magento_Catalog')) { + self::markTestSkipped('Magento_Catalog module disabled.'); + } + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->serializer = $this->objectManager->get(SerializerInterface::class); + $this->productAttributeRepository = $this->objectManager->get(ProductAttributeRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Configurable::class); + $this->request = $this->objectManager->get(RequestInterface::class); + $this->request->clearParams(); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + $this->request->clearParams(); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_images.php + * @return void + */ + public function testPreSelectedGalleryConfig(): void + { + $product = $this->productRepository->get('configurable'); + $this->block->setProduct($product); + $configurableAttribute = $this->productAttributeRepository->get('visual_swatch_attribute'); + $this->request->setQueryValue('visual_swatch_attribute', $configurableAttribute->getOptions()[1]->getValue()); + $jsonConfig = $this->serializer->unserialize($this->block->getJsonConfig()); + $this->assertArrayHasKey('preSelectedGallery', $jsonConfig); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['large']); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['medium']); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['small']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php new file mode 100644 index 0000000000000..096674c5e9620 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductExtensionInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\ProductFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture( + 'Magento/Catalog/_files/product_image.php' +); +Resolver::getInstance()->requireDataFixture( + 'Magento/Swatches/_files/configurable_product_visual_swatch_attribute.php' +); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$images = ['magento_image.jpg', 'magento_small_image.jpg', 'magento_thumbnail.jpg']; +foreach (range(1, 3) as $index) { + $product = $productRepository->get('simple_option_' . $index); + $product->setImage('/m/a/' . $images[$index - 1]) + ->setSmallImage('/m/a/' . $images[$index - 1]) + ->setThumbnail('/m/a/' . $images[$index - 1]) + ->setData('media_gallery', ['images' => [ + [ + 'file' => '/m/a/' . $images[$index - 1], + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + 'media_type' => 'image', + ], + ]]) + ->setCanSaveCustomOptions(true) + ->save(); +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php new file mode 100644 index 0000000000000..c201b258c5341 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture( + 'Magento/Swatches/_files/configurable_product_visual_swatch_attribute_rollback.php' +); +Resolver::getInstance()->requireDataFixture( + 'Magento/Catalog/_files/product_image_rollback.php' +); From a68e58e59a5bf0bd30b0e5b254a867e6d4d9f3bd Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Mon, 28 Dec 2020 11:45:41 +0200 Subject: [PATCH 091/242] MC-39878: Invoice for an order that contains only one configurable product is not generated correctly --- .../Magento/Sales/Model/Order/Invoice.php | 5 ++ .../Magento/Sales/Model/Order/InvoiceTest.php | 69 +++++++++++++++++-- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Invoice.php b/app/code/Magento/Sales/Model/Order/Invoice.php index 14dd0b14ac1f3..50bbb3083a9ea 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Order/Invoice.php @@ -679,6 +679,11 @@ public function register() public function isLast() { foreach ($this->getAllItems() as $item) { + $orderItem = $item->getOrderItem(); + if ($orderItem->isDummy()) { + continue; + } + if (!$item->isLast()) { return false; } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php index 8abec6ac6d734..64d5cdb037343 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php @@ -3,20 +3,57 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\Order; -class InvoiceTest extends \PHPUnit\Framework\TestCase +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Sales\Model\ResourceModel\Order\Collection as OrderCollection; +use Magento\Sales\Api\InvoiceManagementInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; + +/** + * Invoice model test. + */ +class InvoiceTest extends TestCase { /** - * @var \Magento\Sales\Model\ResourceModel\Order\Collection + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var OrderCollection + */ + private $collection; + + /** + * @var InvoiceManagementInterface + */ + private $invoiceManagement; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var SearchCriteriaBuilder */ - private $_collection; + private $searchCriteriaBuilder; + /** + * @inheritDoc + */ protected function setUp(): void { - $this->_collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Sales\Model\ResourceModel\Order\Collection::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->collection = $this->objectManager->create(OrderCollection::class); + $this->invoiceManagement = $this->objectManager->get(InvoiceManagementInterface::class); + $this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $this->searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); } /** @@ -27,9 +64,27 @@ public function testOrderTotalItemCount() $expectedResult = [['total_item_count' => 1]]; $actualResult = []; /** @var \Magento\Sales\Model\Order $order */ - foreach ($this->_collection->getItems() as $order) { + foreach ($this->collection->getItems() as $order) { $actualResult[] = ['total_item_count' => $order->getData('total_item_count')]; } $this->assertEquals($expectedResult, $actualResult); } + + /** + * Test order with exactly one configurable. + * + * @return void + * @magentoDataFixture Magento/Sales/_files/order_configurable_product.php + */ + public function testLastInvoiceWithConfigurable(): void + { + $searchCriteria = $this->searchCriteriaBuilder->addFilter('increment_id', '100000001') + ->create(); + $orders = $this->orderRepository->getList($searchCriteria); + $orders = $orders->getItems(); + $order = array_shift($orders); + $invoice = $this->invoiceManagement->prepareInvoice($order); + + self::assertEquals($invoice->isLast(), true); + } } From 680312b7df1af44ab7b4168f611602b310d292d9 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Mon, 28 Dec 2020 12:39:34 +0200 Subject: [PATCH 092/242] magento/magento2#31251: [MFTF] Refactoring of Search actions on Storefront. --- ...ProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml | 2 +- ...ductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml index b5c04d2ba11f0..52f550248819e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockNotVisibleIndividuallyTest.xml @@ -97,7 +97,7 @@ <!--Verify customer don't see updated simple product link on magento storefront page --> <amOnPage url="{{StorefrontProductPage.url(simpleProductNotVisibleIndividually.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> <argument name="phrase" value="{{simpleProductNotVisibleIndividually.sku}}"/> </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 0d0391ea5a873..daf3833d1fd78 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -126,7 +126,7 @@ <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> <waitForPageLoad stepKey="waitForStoreFrontProductPageLoad"/> - <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillAttribute"> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="fillSimpleProductSkuInSearchTextBox"> <argument name="phrase" value="{{simpleProductRegularPrice245InStock.sku}}"/> </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSearchTextBox"/> From 7491d77c7b8de8a29c5d118796a67f3cb0dcfd8e Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 28 Dec 2020 13:48:51 +0200 Subject: [PATCH 093/242] MC-39575: Create automated test for "Apply visual swatch attribute filter on layered navigation" --- .../Configurable/Listing/ConfigurableTest.php | 11 ----------- .../_files/configurable_product_with_images.php | 14 +++++++------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php index f2d254af85c94..58475ea879094 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php @@ -83,17 +83,6 @@ protected function setUp(): void $this->productRepository->cleanCache(); $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Configurable::class); $this->request = $this->objectManager->get(RequestInterface::class); - $this->request->clearParams(); - } - - /** - * @inheritdoc - */ - protected function tearDown(): void - { - $this->request->clearParams(); - - parent::tearDown(); } /** diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php index 096674c5e9620..f2bcbc27dc01a 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php @@ -7,7 +7,6 @@ use Magento\Catalog\Api\Data\ProductExtensionInterfaceFactory; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Model\ProductFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Workaround\Override\Fixture\Resolver; @@ -21,15 +20,16 @@ $objectManager = Bootstrap::getObjectManager(); /** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); +$configurableProduct = $productRepository->get('configurable'); +$children = $configurableProduct->getTypeInstance()->getUsedProducts($configurableProduct); $images = ['magento_image.jpg', 'magento_small_image.jpg', 'magento_thumbnail.jpg']; -foreach (range(1, 3) as $index) { - $product = $productRepository->get('simple_option_' . $index); - $product->setImage('/m/a/' . $images[$index - 1]) - ->setSmallImage('/m/a/' . $images[$index - 1]) - ->setThumbnail('/m/a/' . $images[$index - 1]) +foreach ($children as $index => $product) { + $product->setImage('/m/a/' . $images[$index]) + ->setSmallImage('/m/a/' . $images[$index]) + ->setThumbnail('/m/a/' . $images[$index]) ->setData('media_gallery', ['images' => [ [ - 'file' => '/m/a/' . $images[$index - 1], + 'file' => '/m/a/' . $images[$index], 'position' => 1, 'label' => 'Image Alt Text', 'disabled' => 0, From 910eb4101338d505fefc48b378082658fc6d7ddf Mon Sep 17 00:00:00 2001 From: "vadim.malesh" <engcom-vendorworker-charlie@adobe.com> Date: Mon, 28 Dec 2020 13:50:49 +0200 Subject: [PATCH 094/242] fixing conflict merge; fixed unit test --- .../Mview/Test/Unit/View/SubscriptionTest.php | 32 +++++++------------ .../Framework/Mview/View/Subscription.php | 23 ++++++------- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php index 256f8d0cb19c7..ef55c71b06281 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php @@ -207,7 +207,7 @@ public function testCreate() ->method('getColumnName') ->willReturn('entity_id'); - $this->viewMock->expects($this->exactly(3)) + $this->viewMock->expects($this->atLeastOnce()) ->method('getChangelog') ->willReturn($changelogMock); @@ -251,17 +251,15 @@ public function testCreate() 'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName'] ] ); - $otherViewMock->expects($this->exactly(3)) + $otherViewMock->expects($this->atLeastOnce()) ->method('getChangelog') ->willReturn($otherChangelogMock); $this->viewMock->expects($this->any()) ->method('getId') ->willReturn('this_id'); - $this->viewMock->expects($this->never()) - ->method('getSubscriptions'); - $this->viewCollectionMock->expects($this->exactly(1)) + $this->viewCollectionMock->expects($this->once()) ->method('getViewsByStateMode') ->with(StateInterface::MODE_ENABLED) ->willReturn([$this->viewMock, $otherViewMock]); @@ -274,8 +272,6 @@ public function testCreate() ->method('createTrigger') ->with($triggerMock); - $this->tableName = 'thisTableName'; - $this->viewMock->expects($this->exactly(3)) ->method('getSubscriptions') ->willReturn( @@ -293,7 +289,7 @@ public function testRemove() $triggerMock = $this->createMock(Trigger::class); $triggerMock->expects($this->exactly(3)) ->method('setName')->willReturnSelf(); - $triggerMock->expects($this->exactly(3)) + $triggerMock->expects($this->any()) ->method('getName') ->willReturn('triggerName'); $triggerMock->expects($this->exactly(3)) @@ -320,7 +316,7 @@ public function testRemove() true, [] ); - $otherChangelogMock->expects($this->exactly(3)) + $otherChangelogMock->expects($this->any()) ->method('getName') ->willReturn('other_test_view_cl'); $otherChangelogMock->expects($this->exactly(3)) @@ -336,17 +332,17 @@ public function testRemove() true, [] ); - - $otherViewMock->expects($this->exactly(1)) + $otherViewMock->expects($this->atLeastOnce()) ->method('getId') ->willReturn('other_id'); - - $otherViewMock->expects($this->exactly(3)) + $otherViewMock->expects($this->atLeastOnce()) ->method('getChangelog') ->willReturn($otherChangelogMock); - $this->viewMock->expects($this->any()) - $otherViewMock->expects($this->any()) + $this->viewMock->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn('this_id'); + $otherViewMock->expects($this->atLeastOnce()) ->method('getSubscriptions') ->willReturn( [ @@ -355,10 +351,6 @@ public function testRemove() ] ); - $this->viewMock->expects($this->exactly(3)) - ->method('getId') - ->willReturn('this_id'); - $this->viewCollectionMock->expects($this->exactly(1)) ->method('getViewsByStateMode') ->with(StateInterface::MODE_ENABLED) @@ -443,7 +435,7 @@ public function testBuildStatementIgnoredColumnSubscriptionLevel(): void 'cataloginventory_stock_item' => ['name' => 'otherTableName', 'column' => 'columnName'] ] ); - $this->viewMock->expects($this->once()) + $this->viewMock->expects($this->atLeastOnce()) ->method('getChangeLog') ->willReturn($otherChangelogMock); diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php index cad9bc6675c1e..03a3bf9615ced 100644 --- a/lib/internal/Magento/Framework/Mview/View/Subscription.php +++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php @@ -10,9 +10,8 @@ use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Ddl\Trigger; -use Magento\Framework\Mview\Config; -use Magento\Framework\Mview\View\StateInterface; use Magento\Framework\DB\Ddl\TriggerFactory; +use Magento\Framework\Mview\Config; use Magento\Framework\Mview\ViewInterface; /** @@ -212,13 +211,14 @@ protected function getLinkedViews() /** * Prepare columns for trigger statement. Should be protected in order to serve new approach * - * @param ChangelogInterface $changelog + * @param ViewInterface $view * @param string $event * @return array * @throws \Exception */ - protected function prepareColumns(ChangelogInterface $changelog, string $event): array + protected function prepareColumns(ViewInterface $view, string $event): array { + $changelog = $view->getChangelog(); $prefix = $event === Trigger::EVENT_DELETE ? 'OLD.' : 'NEW.'; $subscriptionData = $this->mviewConfig->getView($changelog->getViewId())['subscriptions'][$this->getTableName()]; $columns = [ @@ -226,7 +226,7 @@ protected function prepareColumns(ChangelogInterface $changelog, string $event): 'entity_id' => $this->connection->quoteIdentifier($changelog->getColumnName()) ], 'column_values' => [ - 'entity_id' => $this->getEntityColumn($prefix) + 'entity_id' => $this->getEntityColumn($prefix, $view) ] ]; @@ -251,7 +251,6 @@ protected function prepareColumns(ChangelogInterface $changelog, string $event): protected function buildStatement(string $event, ViewInterface $view): string { $trigger = "%sINSERT IGNORE INTO %s (%s) VALUES (%s);"; - $column = $this->getSubscriptionColumn($view); $changelog = $view->getChangelog(); switch ($event) { @@ -286,13 +285,14 @@ protected function buildStatement(string $event, ViewInterface $view): string } break; } - $columns = $this->prepareColumns($changelog, $event); + $columns = $this->prepareColumns($view, $event); + return sprintf( $trigger, $this->getProcessor()->getPreStatements(), $this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())), - implode(", " , $columns['column_names']), - implode(", ", $columns['column_values']) + implode(', ', $columns['column_names']), + implode(', ', $columns['column_values']) ); } @@ -319,11 +319,12 @@ private function getProcessor(): AdditionalColumnProcessorInterface /** * @param string $prefix + * @param ViewInterface $view * @return string */ - public function getEntityColumn(string $prefix): string + public function getEntityColumn(string $prefix, ViewInterface $view): string { - return $prefix . $this->connection->quoteIdentifier($this->getColumnName()); + return $prefix . $this->connection->quoteIdentifier($this->getSubscriptionColumn($view)); } /** From 9e4001b88bd20b2503dc6845a6eae715aa440f4e Mon Sep 17 00:00:00 2001 From: engcom-Kilo <mikola.malevanec@transoftgroup.com> Date: Mon, 28 Dec 2020 16:54:28 +0200 Subject: [PATCH 095/242] MC-39189: Exception on Admin Customers page when website is deleted. --- .../Component/Listing/Column/Confirmation.php | 34 +++-- .../Listing/Column/ConfirmationTest.php | 127 ++++++++++++++++++ 2 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php index 26cac677ccd10..6215909a1fbee 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php @@ -6,6 +6,7 @@ namespace Magento\Customer\Ui\Component\Listing\Column; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Ui\Component\Listing\Columns\Column; @@ -28,7 +29,7 @@ class Confirmation extends Column * @param ScopeConfigInterface $scopeConfig @deprecated * @param array $components * @param array $data - * @param AccountConfirmation $accountConfirmation + * @param AccountConfirmation|null $accountConfirmation * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -65,13 +66,7 @@ public function prepareDataSource(array $dataSource) */ private function getFieldLabel(array $item) { - $isConfirmationRequired = $this->accountConfirmation->isConfirmationRequired( - $item['website_id'][0] ?? null, - $item[$item['id_field_name']], - $item['email'] - ); - - if ($isConfirmationRequired) { + if ($this->getIsConfirmationRequired($item)) { if ($item[$this->getData('name')] === null) { return __('Confirmed'); } @@ -79,4 +74,27 @@ private function getFieldLabel(array $item) } return __('Confirmation Not Required'); } + + /** + * Retrieve is confirmation required flag for customer considering requested website may not exist. + * + * @param array $customer + * @return bool + */ + private function getIsConfirmationRequired(array $customer): bool + { + try { + return $this->accountConfirmation->isConfirmationRequired( + $customer['website_id'][0] ?? null, + $customer[$customer['id_field_name']], + $customer['email'] + ); + } catch (NoSuchEntityException $e) { + return $this->accountConfirmation->isConfirmationRequired( + null, + $customer[$customer['id_field_name']], + $customer['email'] + ); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php b/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php new file mode 100644 index 0000000000000..24fe443c8c796 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php @@ -0,0 +1,127 @@ +<?php + +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Ui\Component\Listing\Column; + +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for \Magento\Customer\Ui\Component\Listing\Column\Confirmation. + */ +class ConfirmationTest extends TestCase +{ + /** + * Test subject. + * + * @var Confirmation + */ + private $confirmation; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->confirmation = Bootstrap::getObjectManager()->create( + Confirmation::class, + [ + 'components' => [], + 'data' => ['name' => 'confirmation'], + ] + ); + } + + /** + * Verify Confirmation::prepareDataSource() won't throw exception in case requested website doesn't exist. + * + * @param array $customerDataSource + * @param array $expectedResult + * @magentoConfigFixture base_website customer/create_account/confirm 1 + * @dataProvider customersDataProvider + * + * @return void + */ + public function testPrepareDataSource(array $customerDataSource, array $expectedResult): void + { + $result = $this->confirmation->prepareDataSource($customerDataSource); + + self::assertEquals($expectedResult, $result); + } + + /** + * CustomerDataSource data provider. + * + * @return array + */ + public function customersDataProvider(): array + { + return [ + [ + 'customerDataSource' => [ + 'data' => [ + 'items' => [ + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '1', + 'name' => 'John Doe', + 'email' => 'john.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:05:50', + 'website_id' => ['1'], + 'confirmation' => false, + 'created_in' => 'Default Store View', + ], + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '2', + 'name' => 'Jane Doe', + 'email' => 'jane.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:06:17', + 'website_id' => ['999999999'], + 'confirmation' => null, + 'created_in' => 'CustomStoreViewWhichDoesNotExistAnymore', + ], + ], + 'totalRecords' => 2, + ], + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '1', + 'name' => 'John Doe', + 'email' => 'john.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:05:50', + 'website_id' => ['1'], + 'confirmation' => __('Confirmation Required'), + 'created_in' => 'Default Store View', + ], + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '2', + 'name' => 'Jane Doe', + 'email' => 'jane.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:06:17', + 'website_id' => ['999999999'], + 'confirmation' => __('Confirmed'), + 'created_in' => 'CustomStoreViewWhichDoesNotExistAnymore', + ], + ], + 'totalRecords' => 2, + ], + ], + ], + ]; + } +} From 7bf378335784b35c66fcf71cce1db2be2399c907 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Mon, 28 Dec 2020 17:35:09 +0200 Subject: [PATCH 096/242] MC-23024: UPS track information request/response was removed from shipping.log --- app/code/Magento/Ups/Model/Carrier.php | 17 ++++++--- .../Magento/Ups/Model/CarrierTest.php | 35 ++++++++++++++++++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 452f488050202..d8fa75e357a66 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -807,21 +807,24 @@ protected function _getXmlQuotes() $httpResponse = $this->asyncHttpClient->request( new Request($url, Request::METHOD_POST, ['Content-Type' => 'application/xml'], $xmlRequest) ); - + $debugData['request'] = $xmlParams; return $this->deferredProxyFactory->create( [ 'deferred' => new CallbackDeferred( - function () use ($httpResponse) { + function () use ($httpResponse, $debugData) { $responseResult = null; $xmlResponse = ''; try { $responseResult = $httpResponse->get(); - } catch (HttpException $exception) { - $this->_logger->critical($exception); + } catch (HttpException $e) { + $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; + $this->_logger->critical($e); } if ($responseResult) { $xmlResponse = $responseResult->getStatusCode() >= 400 ? '' : $responseResult->getBody(); } + $debugData['result'] = $xmlResponse; + $this->_debug($debugData); return $this->_parseXmlResponse($xmlResponse); } @@ -1125,6 +1128,7 @@ protected function _getXmlTracking($trackings) /** @var HttpResponseDeferredInterface[] $trackingResponses */ $trackingResponses = []; $tracking = ''; + $debugData = []; foreach ($trackings as $tracking) { /** * RequestOption==>'1' to request all activities @@ -1141,7 +1145,7 @@ protected function _getXmlTracking($trackings) <IncludeFreight>01</IncludeFreight> </TrackRequest> XMLAuth; - + $debugData[$tracking] = ['request' => $this->filterDebugData($this->_xmlAccessRequest) . $xmlRequest]; $trackingResponses[$tracking] = $this->asyncHttpClient->request( new Request( $url, @@ -1155,6 +1159,8 @@ protected function _getXmlTracking($trackings) $httpResponse = $response->get(); $xmlResponse = $httpResponse->getStatusCode() >= 400 ? '' : $httpResponse->getBody(); + $debugData[$tracking]['result'] = $xmlResponse; + $this->_debug($debugData); $this->_parseXmlTrackingResponse($tracking, $xmlResponse); } @@ -1872,6 +1878,7 @@ public function getShipConfirmUrl() */ public function requestToShipment($request) { + //breakpoint $packages = $request->getPackages(); if (!is_array($packages) || !$packages) { throw new LocalizedException(__('No packages for request')); diff --git a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php index 7000fadd5154d..0cedcca254f80 100644 --- a/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php +++ b/dev/tests/integration/testsuite/Magento/Ups/Model/CarrierTest.php @@ -19,7 +19,9 @@ use Magento\Quote\Model\Quote\Address\RateRequestFactory; use Magento\TestFramework\HTTP\AsyncClientInterfaceMock; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; use Magento\Shipping\Model\Shipment\Request; +use Psr\Log\LoggerInterface; /** * Integration tests for Carrier model class @@ -43,14 +45,32 @@ class CarrierTest extends TestCase */ private $config; + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + + /** + * @var string[] + */ + private $logs = []; + /** * @inheritDoc */ protected function setUp(): void { - $this->carrier = Bootstrap::getObjectManager()->create(Carrier::class); $this->httpClient = Bootstrap::getObjectManager()->get(AsyncClientInterface::class); $this->config = Bootstrap::getObjectManager()->get(ReinitableConfigInterface::class); + $this->logs = []; + $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); + $this->loggerMock->method('debug') + ->willReturnCallback( + function (string $message) { + $this->logs[] = $message; + } + ); + $this->carrier = Bootstrap::getObjectManager()->create(Carrier::class, ['logger' => $this->loggerMock]); } /** @@ -136,6 +156,7 @@ public function testCollectFreeRates() * @magentoConfigFixture default_store carriers/ups/username user * @magentoConfigFixture default_store carriers/ups/password pass * @magentoConfigFixture default_store carriers/ups/access_license_number acn + * @magentoConfigFixture default_store carriers/ups/debug 1 * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR * @magentoConfigFixture default_store currency/options/base GBP */ @@ -172,6 +193,17 @@ public function testCollectRates(int $negotiable, int $tax, int $responseId, str $rates = $this->carrier->collectRates($request)->getAllRates(); $this->assertEquals($price, $rates[0]->getPrice()); $this->assertEquals($method, $rates[0]->getMethod()); + + $requestFound = false; + foreach ($this->logs as $log) { + if (mb_stripos($log, 'RatingServiceSelectionRequest') && + mb_stripos($log, 'RatingServiceSelectionResponse') + ) { + $requestFound = true; + break; + } + } + $this->assertTrue($requestFound); } /** @@ -304,6 +336,7 @@ public function testRequestToShipment(): void * @magentoConfigFixture default_store carriers/ups/username user * @magentoConfigFixture default_store carriers/ups/password pass * @magentoConfigFixture default_store carriers/ups/access_license_number acn + * @magentoConfigFixture default_store carriers/ups/debug 1 * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR * @magentoConfigFixture default_store currency/options/base GBP */ From c5b79d4ce1d82ce165fe2a6954632b0ae6868ba6 Mon Sep 17 00:00:00 2001 From: Serhii Voloshkov <serhii.voloshkov@transoftgroup.com> Date: Tue, 29 Dec 2020 10:29:41 +0200 Subject: [PATCH 097/242] MC-23024: UPS track information request/response was removed from shipping.log --- app/code/Magento/Ups/Model/Carrier.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index d8fa75e357a66..24904ae79abb0 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -1878,7 +1878,6 @@ public function getShipConfirmUrl() */ public function requestToShipment($request) { - //breakpoint $packages = $request->getPackages(); if (!is_array($packages) || !$packages) { throw new LocalizedException(__('No packages for request')); From 640adcdfe746f3d9acf5c6bd7afa24dd2b42a1bb Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 29 Dec 2020 11:15:27 +0200 Subject: [PATCH 098/242] MC-39598: Create automated test for: "Assign/Unassign product to websites via API" --- .../Api/ProductWebsiteLinkRepositoryTest.php | 113 ++++++++++++++++++ .../ProductWebsiteLinkRepositoryTest.php | 72 +++++++++++ 2 files changed, 185 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php new file mode 100644 index 0000000000000..13218450e5054 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php @@ -0,0 +1,113 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Api; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; + +/** + * Tests to check products to websites assigning. + * + * @see \Magento\Catalog\Model\ProductWebsiteLinkRepository + * + * @magentoAppIsolation enabled + */ +class ProductWebsiteLinkRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductWebsiteLinkRepositoryV1'; + const SERVICE_VERSION = 'V1'; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testSaveWebsiteLinkWithoutWebsiteId(): void + { + $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); + $requestData = ['productWebsiteLink' => ['sku' => 'simple2']]; + $this->expectException(\Exception::class); + $this->expectErrorMessage((string)__('There are not websites for assign to product')); + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testSaveWebsiteLinkWithUnexistingWebsiteId(): void + { + $unexistingWebsiteId = 8932568989; + $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); + $requestData = ['productWebsiteLink' => ['sku' => 'simple2', 'websiteId' => $unexistingWebsiteId]]; + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches('/Could not assign product \\\"%1\\\" to websites \\\"%2\\\"/'); + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_with_two_websites.php + * + * @return void + */ + public function testDeleteWebsiteLink(): void + { + $productSku = 'unique-simple-azaza'; + $websiteId = (int)$this->websiteRepository->get('second_website')->getId(); + $resourcePath = sprintf('/V1/products/%s/websites/%u', $productSku, $websiteId); + $serviceInfo = $this->fillServiceInfo($resourcePath, Request::HTTP_METHOD_DELETE, 'Delete'); + $this->_webApiCall($serviceInfo); + $product = $this->productRepository->get($productSku, false, null, true); + $this->assertNotContains($websiteId, $product->getWebsiteIds()); + } + + /** + * Fill service information + * + * @param string $resourcePath + * @param string $httpMethod + * @param string $operation + * @return array + */ + private function fillServiceInfo(string $resourcePath, string $httpMethod, string $operation): array + { + return [ + 'rest' => ['resourcePath' => $resourcePath, 'httpMethod' => $httpMethod], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . $operation, + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php new file mode 100644 index 0000000000000..a4441c9480b25 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model; + +use Magento\Catalog\Api\Data\ProductWebsiteLinkInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\ProductWebsiteLinkRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests to check products to websites assigning. + * + * @see \Magento\Catalog\Model\ProductWebsiteLinkRepository + * + * @magentoAppIsolation enabled + */ +class ProductWebsiteLinkRepositoryTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductWebsiteLinkRepositoryInterface */ + private $productWebsiteLinkRepository; + + /** @var ProductWebsiteLinkInterfaceFactory */ + private $productWebsiteLinkFactory; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productWebsiteLinkRepository = $this->objectManager->get(ProductWebsiteLinkRepositoryInterface::class); + $this->productWebsiteLinkFactory = $this->objectManager->get(ProductWebsiteLinkInterfaceFactory::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_with_two_websites.php + * + * @return void + */ + public function testDelete(): void + { + $this->markTestSkipped('Blocked by MC-40250'); + $productWebsiteLink = $this->productWebsiteLinkFactory->create(); + $productWebsiteLink->setSku('unique-simple-azaza'); + $productWebsiteLink->setWebsiteId(1); + $this->productWebsiteLinkRepository->delete($productWebsiteLink); + $product = $this->productRepository->get('unique-simple-azaza', false, null, true); + $this->assertEquals([$this->websiteRepository->get('second_website')->getId()], $product->getWebsiteIds()); + } +} From 04fd1acd367593c5080075d31602ca7dd68b70ca Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 29 Dec 2020 14:15:22 +0200 Subject: [PATCH 099/242] MC-39598: Create automated test for: "Assign/Unassign product to websites via API" --- .../Api/ProductWebsiteLinkRepositoryTest.php | 21 ++++--------------- .../ProductWebsiteLinkRepositoryTest.php | 17 ++++++++++++++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php index 13218450e5054..fbca54acc9e0b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php @@ -46,20 +46,6 @@ protected function setUp(): void $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); } - /** - * @magentoApiDataFixture Magento/Catalog/_files/second_product_simple.php - * - * @return void - */ - public function testSaveWebsiteLinkWithoutWebsiteId(): void - { - $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); - $requestData = ['productWebsiteLink' => ['sku' => 'simple2']]; - $this->expectException(\Exception::class); - $this->expectErrorMessage((string)__('There are not websites for assign to product')); - $this->_webApiCall($serviceInfo, $requestData); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/second_product_simple.php * @@ -67,11 +53,12 @@ public function testSaveWebsiteLinkWithoutWebsiteId(): void */ public function testSaveWebsiteLinkWithUnexistingWebsiteId(): void { + $pattern = '/(Could\\snot\\sassign\\sproduct)+([\\s\\S]*)(to\\swebsites)+([\\s\\S]*)/'; $unexistingWebsiteId = 8932568989; $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); $requestData = ['productWebsiteLink' => ['sku' => 'simple2', 'websiteId' => $unexistingWebsiteId]]; $this->expectException(\Exception::class); - $this->expectExceptionMessageMatches('/Could not assign product \\\"%1\\\" to websites \\\"%2\\\"/'); + $this->expectExceptionMessageMatches($pattern); $this->_webApiCall($serviceInfo, $requestData); } @@ -85,8 +72,8 @@ public function testDeleteWebsiteLink(): void $productSku = 'unique-simple-azaza'; $websiteId = (int)$this->websiteRepository->get('second_website')->getId(); $resourcePath = sprintf('/V1/products/%s/websites/%u', $productSku, $websiteId); - $serviceInfo = $this->fillServiceInfo($resourcePath, Request::HTTP_METHOD_DELETE, 'Delete'); - $this->_webApiCall($serviceInfo); + $serviceInfo = $this->fillServiceInfo($resourcePath, Request::HTTP_METHOD_DELETE, 'DeleteById'); + $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'websiteId' => $websiteId]); $product = $this->productRepository->get($productSku, false, null, true); $this->assertNotContains($websiteId, $product->getWebsiteIds()); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php index a4441c9480b25..9ae327036971b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php @@ -10,6 +10,7 @@ use Magento\Catalog\Api\Data\ProductWebsiteLinkInterfaceFactory; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Api\ProductWebsiteLinkRepositoryInterface; +use Magento\Framework\Exception\InputException; use Magento\Framework\ObjectManagerInterface; use Magento\Store\Api\WebsiteRepositoryInterface; use Magento\TestFramework\Helper\Bootstrap; @@ -55,7 +56,21 @@ protected function setUp(): void } /** - * @magentoApiDataFixture Magento/Catalog/_files/product_with_two_websites.php + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testSaveWithoutWebsiteId(): void + { + $productWebsiteLink = $this->productWebsiteLinkFactory->create(); + $productWebsiteLink->setSku('unique-simple-azaza'); + $this->expectException(InputException::class); + $this->expectErrorMessage((string)__('There are not websites for assign to product')); + $this->productWebsiteLinkRepository->save($productWebsiteLink); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_with_two_websites.php * * @return void */ From 332ef5de29e285d41090cb8b8c866551ac4fe96e Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Tue, 29 Dec 2020 15:31:58 +0200 Subject: [PATCH 100/242] magento/magento2#31251: [MFTF] Refactoring of Search actions on Storefront. --- ...uctWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 76a768c1b2d21..a9ff81c9c7f87 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -36,9 +36,11 @@ </after> <!-- Search default simple product in the grid --> - <actionGroup ref="AdminClearFiltersActionGroup" stepKey="openProductCatalogPage"/> + <actionGroup ref="FilterAndSelectProductActionGroup" stepKey="openProductCatalogPage"> + <argument name="productSku" value="$initialSimpleProduct.sku$"/> + </actionGroup> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="filterProductGrid"/> - <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickFirstRowToOpenDefaultSimpleProduct"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilProductIsOpened"/> <!-- Update simple product with regular price(in stock) --> @@ -74,8 +76,6 @@ <click selector="{{AdminProductGridFilterSection.applyFilters}}" stepKey="clickApplyFiltersButton"/> <actionGroup ref="AdminOrderGridClickFirstRowActionGroup" stepKey="clickFirstRowToVerifyUpdatedSimpleProductVisibleInGrid"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitUntilSimpleProductPageIsOpened"/> - <!-- <click selector="{{AdminProductGridFilterSection.nthRow('1')}}" stepKey="clickFirstRowToVerifyUpdatedSimpleProductVisibleInGrid"/> - <waitForPageLoad stepKey="waitUntilSimpleProductPageIsOpened"/> --> <!-- Verify customer see updated simple product in the product form page --> <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{simpleProductRegularPrice32501InStock.name}}" stepKey="seeSimpleProductName"/> From 9b0799b75169c7df4e85a647187e15512f71befc Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 29 Dec 2020 19:07:46 +0200 Subject: [PATCH 101/242] MC-39598: Create automated test for: "Assign/Unassign product to websites via API" --- .../Api/ProductWebsiteLinkRepositoryTest.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php index fbca54acc9e0b..0bbed6387ae57 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Api; +use Magento\Catalog\Model\ProductWebsiteLink; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Webapi\Rest\Request; use Magento\Store\Api\WebsiteRepositoryInterface; @@ -56,7 +57,12 @@ public function testSaveWebsiteLinkWithUnexistingWebsiteId(): void $pattern = '/(Could\\snot\\sassign\\sproduct)+([\\s\\S]*)(to\\swebsites)+([\\s\\S]*)/'; $unexistingWebsiteId = 8932568989; $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); - $requestData = ['productWebsiteLink' => ['sku' => 'simple2', 'websiteId' => $unexistingWebsiteId]]; + $requestData = [ + 'productWebsiteLink' => [ + ProductWebsiteLink::KEY_SKU => 'simple2', + ProductWebsiteLink::WEBSITE_ID => $unexistingWebsiteId, + ], + ]; $this->expectException(\Exception::class); $this->expectExceptionMessageMatches($pattern); $this->_webApiCall($serviceInfo, $requestData); @@ -73,7 +79,10 @@ public function testDeleteWebsiteLink(): void $websiteId = (int)$this->websiteRepository->get('second_website')->getId(); $resourcePath = sprintf('/V1/products/%s/websites/%u', $productSku, $websiteId); $serviceInfo = $this->fillServiceInfo($resourcePath, Request::HTTP_METHOD_DELETE, 'DeleteById'); - $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'websiteId' => $websiteId]); + $this->_webApiCall( + $serviceInfo, + [ProductWebsiteLink::KEY_SKU => $productSku, ProductWebsiteLink::WEBSITE_ID => $websiteId] + ); $product = $this->productRepository->get($productSku, false, null, true); $this->assertNotContains($websiteId, $product->getWebsiteIds()); } From 815ef7617724552ef795ccaac5bdf50b75933dae Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Tue, 29 Dec 2020 23:21:25 +0200 Subject: [PATCH 102/242] refactored AdminOrdersReleaseInUnholdStatusTest --- .../Sales/Test/Mftf/Data/HoldOrderData.xml | 17 +++++++ .../Test/Mftf/Metadata/HoldOrderMeta.xml | 17 +++++++ .../AdminOrdersReleaseInUnholdStatusTest.xml | 49 ++++++++++--------- 3 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/HoldOrderData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Metadata/HoldOrderMeta.xml diff --git a/app/code/Magento/Sales/Test/Mftf/Data/HoldOrderData.xml b/app/code/Magento/Sales/Test/Mftf/Data/HoldOrderData.xml new file mode 100644 index 0000000000000..35b72f31f59ac --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/HoldOrderData.xml @@ -0,0 +1,17 @@ +<?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="HoldOrder" type="HoldOrder"> + <var key="quote_id" entityKey="return" entityType="CustomerCart"/> + </entity> + +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Metadata/HoldOrderMeta.xml b/app/code/Magento/Sales/Test/Mftf/Metadata/HoldOrderMeta.xml new file mode 100644 index 0000000000000..66036419815fb --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Metadata/HoldOrderMeta.xml @@ -0,0 +1,17 @@ +<?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="CreateHoldOrder" dataType="HoldOrder" type="create" auth="adminOauth" url="V1/orders/{return}/hold" method="POST"> + <contentType>application/json</contentType> + <object key="cartItem" dataType="CartItem"> + <field key="quote_id">string</field> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml index d2ded1cc73d2b..e0576f94347cf 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminOrdersReleaseInUnholdStatusTest.xml @@ -21,53 +21,56 @@ <before> <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> - <!-- Create Data --> <createData entity="Simple_US_Customer" stepKey="createCustomer"/> <createData entity="_defaultCategory" stepKey="createCategory"/> <createData entity="defaultSimpleProduct" stepKey="createProduct"> <requiredEntity createDataKey="createCategory"/> </createData> + <createData entity="CustomerCart" stepKey="createCustomerCart"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addCartItemOne"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createProduct"/> + </createData> + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddress"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> + <updateData createDataKey="createCustomerCart" entity="CustomerOrderPaymentMethod" stepKey="sendCustomerPaymentInformationOne"> + <requiredEntity createDataKey="createCustomerCart"/> + </updateData> + <createData entity="HoldOrder" stepKey="holdOrder"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> </before> <after> - <!-- Delete data --> <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <!-- Create order --> - <actionGroup ref="CreateOrderActionGroup" stepKey="createFirstOrder"> - <argument name="product" value="$$createProduct$$"/> - <argument name="customer" value="$$createCustomer$$"/> - </actionGroup> - <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> - <assertNotEmpty stepKey="assertOrderIdIsNotEmpty" after="getOrderId"> - <actualResult type="const">$getOrderId</actualResult> - </assertNotEmpty> - - <!-- Hold Order --> - <click selector="{{AdminOrderDetailsMainActionsSection.hold}}" stepKey="pushButtonHold"/> - <waitForPageLoad stepKey="waitForHold"/> - <see userInput="You put the order on hold." stepKey="seeHoldMessage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="createFirstOrder"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="getOrderId"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="assertOrderIdIsNotEmpty"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="pushButtonHold"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForHold"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeHoldMessage"/> - <!-- Navigate to backend: Go to Sales > Orders --> <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="onOrderPage"/> <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> - - <!-- Select Mass Action according to dataset: Unhold --> + <grabTextFrom selector="{{AdminOrdersGridSection.orderIdByIncrementId($createCustomerCart.return$)}}" stepKey="grabOrderId"/> <actionGroup ref="AdminOrderActionOnGridActionGroup" stepKey="actionUnold"> <argument name="action" value="Unhold"/> - <argument name="orderId" value="$getOrderId"/> + <argument name="orderId" value="$grabOrderId"/> </actionGroup> <see userInput="1 order(s) have been released from on hold status." stepKey="assertOrderReleaseSuccessMessage"/> - <!--Assert order in orders grid --> <actionGroup ref="AdminOrderFilterByOrderIdAndStatusActionGroup" stepKey="seeFirstOrder"> - <argument name="orderId" value="{$getOrderId}"/> + <argument name="orderId" value="{$grabOrderId}"/> <argument name="orderStatus" value="Pending"/> </actionGroup> - <see userInput="{$getOrderId}" selector="{{AdminOrdersGridSection.gridCell('1','ID')}}" stepKey="assertOrderID"/> + <see userInput="{$grabOrderId}" selector="{{AdminOrdersGridSection.gridCell('1','ID')}}" stepKey="assertOrderID"/> <see userInput="Pending" selector="{{AdminOrdersGridSection.gridCell('1','Status')}}" stepKey="assertOrderStatus"/> </test> </tests> From 2740e08869dfc8b0ea69bd20400c693e82c73a1b Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 30 Dec 2020 13:01:01 +0200 Subject: [PATCH 103/242] MC-40068: Create automated test for: "Try to delete root category by API call" --- .../Catalog/Api/CategoryRepositoryTest.php | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php index 5623edca62b9a..8e0aff81cc3b8 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php @@ -184,22 +184,49 @@ public function testDeleteNoSuchEntityException() /** * @dataProvider deleteSystemOrRootDataProvider + * + * @param int $categoryId + * @param string $exceptionMsg + * @return void */ - public function testDeleteSystemOrRoot() + public function testDeleteSystemOrRoot(int $categoryId, string $exceptionMsg): void { $this->expectException(\Exception::class); + $this->expectExceptionMessage($exceptionMsg); - $this->deleteCategory($this->modelId); + $this->deleteCategory($categoryId); } - public function deleteSystemOrRootDataProvider() + /** + * @return array + */ + public function deleteSystemOrRootDataProvider(): array { return [ - [Category::TREE_ROOT_ID], - [2] //Default root category + 'system_category' => [ + 'category_id' => Category::TREE_ROOT_ID, + 'exception_message' => $this->buildExceptionMessage(Category::TREE_ROOT_ID), + ], + 'root_category' => [ + 'category_id' => 2, + 'exception_message' => $this->buildExceptionMessage(2), + ], ]; } + /** + * Build response error message + * + * @param int $categoryId + * @return string + */ + private function buildExceptionMessage(int $categoryId): string + { + $translatedMsg = (string)__('Cannot delete category with id %1'); + + return sprintf('{"message":"%s","parameters":["%u"]}', $translatedMsg, $categoryId); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/category.php */ From 3be83d097274766dd8c2c2b1d98ae2baf5f0b17b Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Wed, 30 Dec 2020 13:52:39 +0200 Subject: [PATCH 104/242] MC-38423: Some Elements of the Shopping Cart page are overlapped with certain view --- .../view/frontend/templates/cart/item/default.phtml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml index 0267f68c5f81d..6937bb54baa08 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml @@ -48,7 +48,11 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <dt><?= $block->escapeHtml($_option['label']) ?></dt> <dd> <?php if (isset($_formatedOptionValue['full_view'])) :?> - <?= $block->escapeHtml($_formatedOptionValue['full_view']) ?> + <?php if (strlen($_formatedOptionValue['full_view']) <= 100) :?> + <?= $block->escapeHtml($_formatedOptionValue['full_view']) ?> + <?php else :?> + <?= $block->escapeHtml($_formatedOptionValue['value'], ['span', 'a']) ?> + <?php endif; ?> <?php else :?> <?= $block->escapeHtml($_formatedOptionValue['value'], ['span', 'a']) ?> <?php endif; ?> From 14f3af27d67db2f807fa413fe013b15ce48857f9 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Wed, 30 Dec 2020 14:12:45 +0200 Subject: [PATCH 105/242] MC-39470: issue with dynamicRows component --- .../base/web/js/dynamic-rows/dynamic-rows.js | 18 +++++++--- .../base/js/dynamic-rows/dynamic-rows.test.js | 33 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js index 0ac35df78e001..45dfaa40f87df 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js @@ -620,15 +620,12 @@ define([ * @param {Array} data */ parsePagesData: function (data) { - var pages; - this.relatedData = this.deleteProperty ? _.filter(data, function (elem) { return elem && elem[this.deleteProperty] !== this.deleteValue; }, this) : data; - pages = Math.ceil(this.relatedData.length / this.pageSize) || 1; - this.pages(pages); + this._updatePagesQuantity(); }, /** @@ -885,6 +882,18 @@ define([ this._sort(); }, + /** + * Update number of pages. + * + * @private + * @return void + */ + _updatePagesQuantity: function () { + var pages = Math.ceil(this.relatedData.length / this.pageSize) || 1; + + this.pages(pages); + }, + /** * Reduce the number of pages * @@ -960,6 +969,7 @@ define([ reload: function () { this.clear(); this.initChildren(false, true); + this._updatePagesQuantity(); /* After change page size need to check existing current page */ this._reducePages(); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js index fc60fbb0bdccc..1101770b0faa2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js @@ -171,5 +171,38 @@ define([ }; expect(JSON.stringify(model.labels())).toEqual(JSON.stringify(result)); }); + + it('Check _updatePagesQuantity method call.', function () { + model._updatePagesQuantity = jasmine.createSpy(); + + model.reload(); + + expect(model._updatePagesQuantity).toHaveBeenCalled(); + }); + + it('Check number of pages is updated after reloading dynamic-rows.', function () { + model.pageSize = 1; + model.relatedData = [ + { + name: 'first' + }, + { + name: 'second' + }, + { + name: 'third' + } + ]; + + model.reload(); + expect(model.pages()).toEqual(3); + + model.currentPage(3); + model.pageSize = 2; + + model.reload(); + expect(model.pages()).toEqual(2); + expect(model.currentPage()).toEqual(2); + }); }); }); From 10fe506d9489296e9c4b27666d3c687c07b8ba57 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 30 Dec 2020 14:16:56 +0200 Subject: [PATCH 106/242] MC-39702: Create automated test for: "Visual swatch on the product page" --- .../Product/Renderer/ConfigurableTest.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php index c900d276c7864..111d0aa08f7f5 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php @@ -148,6 +148,32 @@ public function testGetJsonSwatchConfigUsedProductImage(): void ); } + /** + * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_visual_swatch_attribute.php + * @magentoDataFixture Magento/Catalog/_files/product_image.php + * @return void + */ + public function testGetJsonSwatchConfigUsedWithSwatchImageType(): void + { + $this->updateAttributeUseProductImageFlag(); + $this->updateProductImage('simple_option_2', '/m/a/magento_image.jpg'); + $this->setSwatchImage('simple_option_2', '/m/a/magento_image.jpg'); + $expectedOptions = $this->getDefaultOptionsList(); + $expectedOptions['option 2']['value'] = $this->imageUrlBuilder->getUrl( + '/m/a/magento_image.jpg', + 'swatch_image_base' + ); + $expectedOptions['option 2']['thumb'] = $this->imageUrlBuilder->getUrl( + '/m/a/magento_image.jpg', + 'swatch_thumb_base' + ); + $this->assertOptionsData( + $this->serializer->unserialize($this->block->getJsonSwatchConfig()), + $expectedOptions, + ['swatch_input_type' => 'visual', 'use_product_image_for_swatch' => 1] + ); + } + /** * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_visual_swatch_attribute.php * @return void @@ -249,4 +275,18 @@ private function updateProductImage(string $sku, string $imageName): void ->setCanSaveCustomOptions(true); $this->productResource->save($product); } + + /** + * Set swatch image for a Product. + * + * @param string $sku + * @param string $imageName + * @return void + */ + private function setSwatchImage(string $sku, string $imageName): void + { + $product = $this->productRepository->get($sku); + $product->setSwatchImage($imageName)->save($product); + } } + From bd329b681eeab9b667f2fcbe4a1aa67d23d4b3e3 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Wed, 30 Dec 2020 14:46:51 +0200 Subject: [PATCH 107/242] MC-40030: Wrong currency sign in Credit Memo grid with Website scope for Price --- app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php index 4ffb6f98447c7..cc323730f14b4 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php @@ -10,6 +10,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\Pricing\PriceCurrencyInterface; @@ -77,8 +78,10 @@ public function prepareDataSource(array $dataSource) foreach ($dataSource['data']['items'] as & $item) { $currencyCode = isset($item['base_currency_code']) ? $item['base_currency_code'] : null; if (!$currencyCode) { + $storeId = isset($item['store_id']) && (int)$item['store_id'] !== 0 ? $item['store_id'] : + $this->context->getFilterParam('store_id', Store::DEFAULT_STORE_ID); $store = $this->storeManager->getStore( - $this->context->getFilterParam('store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID) + $storeId ); $currencyCode = $store->getBaseCurrency()->getCurrencyCode(); } From 16826bd19568a4df154f2fc787e2a89d99a2e46a Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Wed, 30 Dec 2020 15:01:03 +0200 Subject: [PATCH 108/242] MC-39687: Create automated test for: "Set backorders "Allow Qty Below 0" and check indexers" --- .../Model/Config/Backend/BackordersTest.php | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php new file mode 100644 index 0000000000000..279e45fc868cc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Model\Config\Backend; + +use Magento\CatalogInventory\Model\Configuration; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; +use Magento\CatalogInventory\Model\Stock; +use Magento\Config\Model\Config\BackendFactory; +use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\Indexer\StateInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks that the backorders config backend model is working correctly + */ +class BackordersTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Backorders */ + private $backorders; + + /** @var BackendFactory */ + private $backendFactory; + + /** @var MutableScopeConfigInterface */ + private $mutableConfig; + + /** @var Processor */ + private $stockIndexerProcessor; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->backendFactory = $this->objectManager->create(BackendFactory::class); + $this->backorders = $this->backendFactory->create(Backorders::class, [ + 'data' => [ + 'path' => Configuration::XML_PATH_BACKORDERS, + ] + ]); + $this->mutableConfig = $this->objectManager->get(MutableScopeConfigInterface::class); + $this->stockIndexerProcessor = $this->objectManager->get(Processor::class); + } + + /** + * @dataProvider afterSaveDataProvider + * @param int $value + * @param int $currentValue + * @param string $expectedIndexerStatus + * @magentoDbIsolation disabled + * @return void + */ + public function testAfterSave(int $value, int $currentValue, string $expectedIndexerStatus): void + { + $this->stockIndexerProcessor->reindexAll(); + $this->mutableConfig->setValue(Configuration::XML_PATH_BACKORDERS, $currentValue); + $this->backorders->setValue((string)$value); + $this->backorders->afterSave(); + + $this->assertEquals($expectedIndexerStatus, $this->stockIndexerProcessor->getIndexer()->getStatus()); + } + + /** + * Data provider for testAfterSave + * + * @return array + */ + public function afterSaveDataProvider(): array + { + return [ + 'set_backorders' => [ + 'value' => Stock::BACKORDERS_YES_NONOTIFY, + 'current_value' => Stock::BACKORDERS_NO, + 'expected_indexer_status' => StateInterface::STATUS_INVALID, + ], + 'unset_backorders' => [ + 'value' => Stock::BACKORDERS_NO, + 'current_value' => Stock::BACKORDERS_YES_NONOTIFY, + 'expected_indexer_status' => StateInterface::STATUS_INVALID, + ], + 'same_backorders' => [ + 'value' => Stock::BACKORDERS_YES_NONOTIFY, + 'current_value' => Stock::BACKORDERS_YES_NONOTIFY, + 'expected_indexer_status' => StateInterface::STATUS_VALID, + ], + ]; + } +} From 048ada376695b0df9b5d63ab4a321a8d7302477c Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 30 Dec 2020 15:24:22 +0200 Subject: [PATCH 109/242] MC-40068: Create automated test for: "Try to delete root category by API call" --- .../testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php index 8e0aff81cc3b8..2e8eedf96b0f8 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php @@ -224,7 +224,9 @@ private function buildExceptionMessage(int $categoryId): string { $translatedMsg = (string)__('Cannot delete category with id %1'); - return sprintf('{"message":"%s","parameters":["%u"]}', $translatedMsg, $categoryId); + return TESTS_WEB_API_ADAPTER === self::ADAPTER_REST + ? sprintf('{"message":"%s","parameters":["%u"]}', $translatedMsg, $categoryId) + : $translatedMsg; } /** From c50560110e4eb940f07566ad66915c5ee58de60b Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 30 Dec 2020 15:37:34 +0200 Subject: [PATCH 110/242] MC-39702: Create automated test for: "Visual swatch on the category page" --- .../Product/Renderer/ConfigurableTest.php | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php index 111d0aa08f7f5..5c5b1399caed8 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php @@ -156,8 +156,7 @@ public function testGetJsonSwatchConfigUsedProductImage(): void public function testGetJsonSwatchConfigUsedWithSwatchImageType(): void { $this->updateAttributeUseProductImageFlag(); - $this->updateProductImage('simple_option_2', '/m/a/magento_image.jpg'); - $this->setSwatchImage('simple_option_2', '/m/a/magento_image.jpg'); + $this->updateProductImage('simple_option_2', '/m/a/magento_image.jpg', ['swatch_image']); $expectedOptions = $this->getDefaultOptionsList(); $expectedOptions['option 2']['value'] = $this->imageUrlBuilder->getUrl( '/m/a/magento_image.jpg', @@ -249,15 +248,16 @@ private function updateAttributeUseProductImageFlag(): void * * @param string $sku * @param string $imageName + * @param array $imageRoles * @return void */ - private function updateProductImage(string $sku, string $imageName): void - { + private function updateProductImage( + string $sku, + string $imageName, + array $imageRoles = ['image', 'small_image', 'thumbnail'] + ): void { $product = $this->productRepository->get($sku); $product->setStoreId(Store::DEFAULT_STORE_ID) - ->setImage($imageName) - ->setSmallImage($imageName) - ->setThumbnail($imageName) ->setData( 'media_gallery', [ @@ -273,20 +273,10 @@ private function updateProductImage(string $sku, string $imageName): void ] ) ->setCanSaveCustomOptions(true); - $this->productResource->save($product); - } + foreach ($imageRoles as $role) { + $product->setData($role, $imageName); + } - /** - * Set swatch image for a Product. - * - * @param string $sku - * @param string $imageName - * @return void - */ - private function setSwatchImage(string $sku, string $imageName): void - { - $product = $this->productRepository->get($sku); - $product->setSwatchImage($imageName)->save($product); + $this->productResource->save($product); } } - From 10272105edddaca5363e1e16ea033184b33dd009 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Thu, 31 Dec 2020 09:47:11 +0200 Subject: [PATCH 111/242] MC-40030: Wrong currency sign in Credit Memo grid with Website scope for Price --- .../Ui/Component/Listing/Column/PriceTest.php | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php index 4a9061c3f3c5c..449ab230b568d 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php @@ -17,6 +17,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Contains tests for Price class + */ class PriceTest extends TestCase { /** @@ -34,6 +37,9 @@ class PriceTest extends TestCase */ private $storeManagerMock; + /** + * @inheritDoc + */ protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -57,12 +63,20 @@ protected function setUp(): void } /** - * @param $hasCurrency - * @param $dataSource - * @param $currencyCode + * Test for prepareDataSource method + * + * @param bool $hasCurrency + * @param array $dataSource + * @param string $currencyCode + * @param int|null $expectedStoreId * @dataProvider testPrepareDataSourceDataProvider */ - public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) + public function testPrepareDataSource( + bool $hasCurrency, + array $dataSource, + string $currencyCode, + ?int $expectedStoreId = null + ): void { $itemName = 'itemName'; $oldItemValue = 'oldItemValue'; @@ -79,6 +93,7 @@ public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) ->willReturn($currencyCode); $this->storeManagerMock->expects($hasCurrency ? $this->never() : $this->once()) ->method('getStore') + ->with($expectedStoreId) ->willReturn($store); $store->expects($hasCurrency ? $this->never() : $this->once()) ->method('getBaseCurrency') @@ -98,7 +113,12 @@ public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) $this->assertEquals($newItemValue, $dataSource['data']['items'][0][$itemName]); } - public function testPrepareDataSourceDataProvider() + /** + * Provider for testPrepareDataSource + * + * @return array + */ + public function testPrepareDataSourceDataProvider(): array { $dataSource1 = [ 'data' => [ @@ -119,9 +139,31 @@ public function testPrepareDataSourceDataProvider() ] ] ]; + $dataSource3 = [ + 'data' => [ + 'items' => [ + [ + 'itemName' => 'oldItemValue', + 'store_id' => '2' + ] + ] + ] + ]; + $dataSource4 = [ + 'data' => [ + 'items' => [ + [ + 'itemName' => 'oldItemValue', + 'store_id' => 'abc' + ] + ] + ] + ]; return [ [true, $dataSource1, 'US'], [false, $dataSource2, 'SAR'], + [false, $dataSource3, 'SAR', 2], + [false, $dataSource4, 'SAR'], ]; } } From 62bb82c0e93a8085f7a0d5f479ff225896c45385 Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Thu, 31 Dec 2020 11:54:45 +0200 Subject: [PATCH 112/242] MC-30104: When using MysqlMQ messages are always set to complete even if exception occurs --- .../MessageQueue/Model/ResourceModel/Lock.php | 48 ++++---- .../TestModuleMysqlMq/Model/Processor.php | 25 +++- .../TestModuleMysqlMq/etc/communication.xml | 1 + .../Magento/TestModuleMysqlMq/etc/queue.xml | 3 + .../TestModuleMysqlMq/etc/queue_consumer.xml | 1 + .../TestModuleMysqlMq/etc/queue_publisher.xml | 3 + .../TestModuleMysqlMq/etc/queue_topology.xml | 1 + .../MessageQueue/Model/ConsumerTest.php | 109 ++++++++++++++++++ .../Model/ResourceModel/LockTest.php | 28 +++++ 9 files changed, 193 insertions(+), 26 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php create mode 100644 dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php b/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php index 16c02a7505664..00399e30e8b72 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php @@ -5,46 +5,52 @@ */ namespace Magento\MessageQueue\Model\ResourceModel; -use \Magento\Framework\MessageQueue\Lock\ReaderInterface; -use \Magento\Framework\MessageQueue\Lock\WriterInterface; +use DateInterval; +use DateTime; +use Magento\Framework\MessageQueue\Lock\ReaderInterface; +use Magento\Framework\MessageQueue\Lock\WriterInterface; +use Magento\Framework\MessageQueue\LockInterface; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Magento\MessageQueue\Model\LockFactory; /** * Class Lock to handle database lock table db transactions. */ -class Lock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb implements ReaderInterface, WriterInterface +class Lock extends AbstractDb implements ReaderInterface, WriterInterface { /**#@+ * Constants */ - const QUEUE_LOCK_TABLE = 'queue_lock'; + public const QUEUE_LOCK_TABLE = 'queue_lock'; /**#@-*/ /**#@-*/ private $dateTime; /** - * @var \Magento\MessageQueue\Model\LockFactory + * @var LockFactory */ private $lockFactory; /** - * @var integer + * @var int */ private $interval; /** * Initialize dependencies. * - * @param \Magento\Framework\Model\ResourceModel\Db\Context $context + * @param Context $context * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime - * @param \Magento\MessageQueue\Model\LockFactory $lockFactory - * @param null $connectionName - * @param integer $interval + * @param LockFactory $lockFactory + * @param ?string $connectionName + * @param int $interval */ public function __construct( - \Magento\Framework\Model\ResourceModel\Db\Context $context, + Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $dateTime, - \Magento\MessageQueue\Model\LockFactory $lockFactory, + LockFactory $lockFactory, $connectionName = null, $interval = 86400 ) { @@ -55,7 +61,7 @@ public function __construct( } /** - * {@inheritDoc} + * @inheritdoc */ protected function _construct() { @@ -63,9 +69,9 @@ protected function _construct() } /** - * {@inheritDoc} + * @inheritdoc */ - public function read(\Magento\Framework\MessageQueue\LockInterface $lock, $code) + public function read(LockInterface $lock, $code) { $object = $this->lockFactory->create(); $object->load($code, 'message_code'); @@ -75,23 +81,25 @@ public function read(\Magento\Framework\MessageQueue\LockInterface $lock, $code) } /** - * {@inheritDoc} + * @inheritdoc */ - public function saveLock(\Magento\Framework\MessageQueue\LockInterface $lock) + public function saveLock(LockInterface $lock) { $object = $this->lockFactory->create(); $object->setMessageCode($lock->getMessageCode()); $object->setCreatedAt($this->dateTime->gmtTimestamp()); $object->save(); + $lock->setId($object->getId()); + $lock->setCreatedAt($object->getCreatedAt()); } /** - * {@inheritDoc} + * @inheritdoc */ public function releaseOutdatedLocks() { - $date = (new \DateTime())->setTimestamp($this->dateTime->gmtTimestamp()); - $date->add(new \DateInterval('PT' . $this->interval . 'S')); + $date = (new DateTime())->setTimestamp($this->dateTime->gmtTimestamp()); + $date->add(new DateInterval('PT' . $this->interval . 'S')); $this->getConnection()->delete($this->getTable(self::QUEUE_LOCK_TABLE), ['created_at <= ?' => $date]); } } diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php index fb6fd4c5c2802..3d2f722ccb60e 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php @@ -5,13 +5,16 @@ */ namespace Magento\TestModuleMysqlMq\Model; +use LogicException; +use Magento\Framework\MessageQueue\ConnectionLostException; + /** * Test message processor is used by \Magento\MysqlMq\Model\PublisherConsumerTest */ class Processor { /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processMessage($message) { @@ -23,7 +26,7 @@ public function processMessage($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processObjectCreated($message) { @@ -35,7 +38,7 @@ public function processObjectCreated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processCustomObjectCreated($message) { @@ -47,7 +50,7 @@ public function processCustomObjectCreated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processObjectUpdated($message) { @@ -59,13 +62,23 @@ public function processObjectUpdated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processMessageWithException($message) { file_put_contents($message->getOutputPath(), "Exception processing {$message->getEntityId()}"); - throw new \LogicException( + throw new LogicException( "Exception during message processing happened. Entity: {{$message->getEntityId()}}" ); } + + /** + * @throws ConnectionLostException + */ + public function processMessageWithConnectionException() + { + throw new ConnectionLostException( + "Connection exception during message processing happened." + ); + } } diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml index 4d6269dbb7920..1a5a5feb11324 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml @@ -7,6 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd"> <topic name="demo.exception" request="Magento\TestModuleMysqlMq\Model\DataObject"/> + <topic name="demo.connection.exception" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="test.schema.defined.by.method" schema="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation" is_synchronous="false"/> <topic name="demo.object.created" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="demo.object.updated" request="Magento\TestModuleMysqlMq\Model\DataObject"/> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml index 362237c0c5e62..c879b271c6651 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml @@ -9,6 +9,9 @@ <broker topic="demo.exception" type="db" exchange="magento"> <queue consumer="demoConsumerWithException" name="queue-exception" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithException"/> </broker> + <broker topic="demo.connection.exception" type="db" exchange="magento"> + <queue consumer="demoConsumerWithConnectionException" name="queue-connection-exception" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithConnectionException"/> + </broker> <broker topic="test.schema.defined.by.method" type="db" exchange="magento"> <queue consumer="delayedOperationConsumer" name="demo-queue-6" handler="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation"/> </broker> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml index bb495a123a05d..6a3916a23b43b 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml @@ -10,5 +10,6 @@ <consumer name="demoConsumerQueueTwo" queue="queue-updated" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processObjectUpdated"/> <consumer name="demoConsumerQueueThree" queue="queue-custom-created" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processCustomObjectCreated"/> <consumer name="demoConsumerWithException" queue="queue-exception" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithException"/> + <consumer name="demoConsumerWithConnectionException" queue="queue-connection-exception" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithConnectionException"/> <consumer name="delayedOperationConsumer" queue="demo-queue-6" connection="db" handler="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation"/> </config> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml index a665e10ef5f14..639503a936cb5 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml @@ -9,6 +9,9 @@ <publisher topic="demo.exception"> <connection name="db" exchange="magento"/> </publisher> + <publisher topic="demo.connection.exception"> + <connection name="db" exchange="magento"/> + </publisher> <publisher topic="test.schema.defined.by.method"> <connection name="db" exchange="magento"/> </publisher> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml index 2df5485ee3447..3612438c37f4a 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml @@ -9,6 +9,7 @@ <exchange name="magento" type="topic" connection="db"> <binding id="demo.exception.consumer" topic="demo.exception" destination="queue-exception" destinationType="queue"/> + <binding id="demo.connection.exception.consumer" topic="demo.connection.exception" destination="queue-connection-exception" destinationType="queue"/> <binding id="test.schema.defined.by.method" topic="test.schema.defined.by.method" destination="demo-queue-6" destinationType="queue"/> <binding id="demo.object.created" topic="demo.object.created" destination="queue-created" destinationType="queue"/> <binding id="demo.object.updated" topic="demo.object.updated" destination="queue-updated" destinationType="queue"/> diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php new file mode 100644 index 0000000000000..a3515b07f1e0b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php @@ -0,0 +1,109 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MessageQueue\Model; + +use Magento\Framework\MessageQueue\Consumer; +use Magento\Framework\MessageQueue\ConsumerFactory; +use Magento\Framework\MessageQueue\EnvelopeFactory; +use Magento\Framework\MessageQueue\QueueInterface; +use Magento\MysqlMq\Model\QueueManagement; +use Magento\MysqlMq\Model\ResourceModel\Queue; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Tests the different cases of consumers running by Consumer processor + */ +class ConsumerTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Consumer + */ + private $model; + + /** + * @var Queue + */ + private $queueResource; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = ObjectManager::getInstance(); + /** @var ConsumerFactory $factory */ + $factory = $this->objectManager->get(ConsumerFactory::class); + $this->model = $factory->get('demoConsumerWithConnectionException'); + $this->queueResource = $this->objectManager->get(Queue::class); + } + + /** + * Test if after connection exception and retry + * message doesn't have success status but still has status in progress + * + * @return void + */ + public function testRunWithException(): void + { + /** @var EnvelopeFactory $envelopFactory */ + $envelopFactory = $this->objectManager->get(EnvelopeFactory::class); + $messageBody = '{"name":"test"}'; + $topicName = 'demo.connection.exception'; + $queueName = 'queue-connection-exception'; + $envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => ['topic_name' => $topicName]]); + /** @var QueueInterface $queue */ + $queue = $this->objectManager->create( + \Magento\MysqlMq\Model\Driver\Queue::class, + ['queueName' => $queueName] + ); + $queue->push($envelope); + $messages = $this->queueResource->getMessages($queueName, 1); + $envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => $messages[0]]); + $this->model->process(1); + $queue->reject($envelope); + $this->model->process(1); + $message = $this->getLastMessage($queueName); + $this->assertEquals(QueueManagement::MESSAGE_STATUS_IN_PROGRESS, $message['status']); + } + + /** + * Return last message by queue name + * + * @param string $queueName + * @return array + */ + private function getLastMessage(string $queueName) + { + $connection = $this->queueResource->getConnection(); + $select = $connection->select() + ->from( + ['queue_message' => $this->queueResource->getTable('queue_message')], + [] + )->join( + ['queue_message_status' => $this->queueResource->getTable('queue_message_status')], + 'queue_message.id = queue_message_status.message_id', + [ + QueueManagement::MESSAGE_QUEUE_RELATION_ID => 'id', + QueueManagement::MESSAGE_STATUS => 'status', + ] + )->join( + ['queue' => $this->queueResource->getTable('queue')], + 'queue.id = queue_message_status.queue_id', + [QueueManagement::MESSAGE_QUEUE_NAME => 'name'] + )->where('queue.name = ?', $queueName) + ->order(['queue_message_status.id DESC']); + + return $connection->fetchRow($select); + } +} diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php new file mode 100644 index 0000000000000..bede370db29c4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MessageQueue\Model\ResourceModel; + +use Magento\Framework\MessageQueue\LockInterface; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Covers Lock resource model test cases + */ +class LockTest extends TestCase +{ + public function testSaveLock() + { + $objectManager = ObjectManager::getInstance(); + /** @var Lock $resourceModel */ + $resourceModel = $objectManager->get(Lock::class); + $lock = $objectManager->create(LockInterface::class); + $resourceModel->saveLock($lock); + self::assertNotEquals(null, $lock->getId()); + } +} From 025c6b784301621ecfc33f1a4242b89a31e16692 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 31 Dec 2020 14:03:04 +0200 Subject: [PATCH 113/242] MC-40148: Create automated test for: "Set decimal Qty increment" --- .../Config/Backend/QtyincrementsTest.php | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php new file mode 100644 index 0000000000000..4ca993129de76 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Model\System\Config\Backend; + +use Magento\CatalogInventory\Model\Configuration; +use Magento\Config\Model\Config\BackendFactory; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks that the qty increments config backend model is working correctly + */ +class QtyincrementsTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Qtyincrements */ + private $qtyIncrements; + + /** @var BackendFactory */ + private $backendFactory; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->backendFactory = $this->objectManager->create(BackendFactory::class); + $this->qtyIncrements = $this->backendFactory->create(Qtyincrements::class, [ + 'data' => [ + 'path' => Configuration::XML_PATH_QTY_INCREMENTS, + ] + ]); + } + + /** + * @return void + */ + public function testAfterSaveWithDecimals(): void + { + $this->expectException(LocalizedException::class); + $this->expectExceptionMessage((string)__("Quantity increments can't use decimals. Enter a new increment and try again.")); + $value = 10.5; + $this->qtyIncrements->setValue((string)$value); + $this->qtyIncrements->beforeSave(); + } +} From 79887430a29094e13dbdbc084a4ed8c06f19474e Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Wed, 30 Dec 2020 13:33:06 +0200 Subject: [PATCH 114/242] MC-30127: Product Price is mismatch in invoice and invoice PDF magento for Bundle Product 2.2.1 --- .../Model/Sales/Order/Pdf/Items/Invoice.php | 152 +++++--- .../Sales/Order/Pdf/Items/InvoiceTest.php | 352 ++++++++++++++++++ 2 files changed, 460 insertions(+), 44 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php index 64e9f56dd65bc..26d0fd274014c 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php @@ -8,6 +8,7 @@ namespace Magento\Bundle\Model\Sales\Order\Pdf\Items; use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\DataObject; use Magento\Framework\Filesystem; use Magento\Framework\Filter\FilterManager; use Magento\Framework\Model\Context; @@ -69,34 +70,38 @@ public function __construct( } /** - * Draw item line + * Draw bundle product item line * * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function draw() { - $order = $this->getOrder(); - $item = $this->getItem(); - $pdf = $this->getPdf(); - $page = $this->getPage(); + $draw = $this->drawChildrenItems(); + $draw = $this->drawCustomOptions($draw); + $page = $this->getPdf()->drawLineBlocks($this->getPage(), $draw, ['table_header' => true]); + + $this->setPage($page); + } + + /** + * Draw bundle product children items + * + * @return array + */ + private function drawChildrenItems(): array + { $this->_setFontRegular(); - $items = $this->getChildren($item); $prevOptionId = ''; $drawItems = []; - - foreach ($items as $childItem) { - $line = []; - + $optionId = 0; + foreach ($this->getChildren($this->getItem()) as $childItem) { + $lines = []; + $index = array_key_last($lines) !== null ? array_key_last($lines) + 1 : 0; $attributes = $this->getSelectionAttributes($childItem); if (is_array($attributes)) { $optionId = $attributes['option_id']; - } else { - $optionId = 0; } if (!isset($drawItems[$optionId])) { @@ -104,15 +109,14 @@ public function draw() } if ($childItem->getOrderItem()->getParentItem() && $prevOptionId != $attributes['option_id']) { - $line[0] = [ + $lines[$index][] = [ 'font' => 'italic', 'text' => $this->string->split($attributes['option_label'], 45, true, true), 'feed' => 35, ]; - $drawItems[$optionId] = ['lines' => [$line], 'height' => 15]; - - $line = []; + $drawItems[$optionId] = ['height' => 15]; + $index++; $prevOptionId = $attributes['option_id']; } @@ -124,35 +128,97 @@ public function draw() $feed = 35; $name = $childItem->getName(); } - $line[] = ['text' => $this->string->split($name, 35, true, true), 'feed' => $feed]; + $lines[$index][] = ['text' => $this->string->split($name, 35, true, true), 'feed' => $feed]; - // draw SKUs - if (!$childItem->getOrderItem()->getParentItem()) { - $text = []; - foreach ($this->string->split($item->getSku(), 17) as $part) { - $text[] = $part; - } - $line[] = ['text' => $text, 'feed' => 255]; - } + $lines = $this->drawSkus($childItem, $lines); - // draw prices - if ($this->canShowPriceInfo($childItem)) { - $price = $order->formatPriceTxt($childItem->getPrice()); - $line[] = ['text' => $price, 'feed' => 395, 'font' => 'bold', 'align' => 'right']; - $line[] = ['text' => $childItem->getQty() * 1, 'feed' => 435, 'font' => 'bold']; + $lines = $this->drawPrices($childItem, $lines); + $drawItems[$optionId]['lines'] = $lines; + } - $tax = $order->formatPriceTxt($childItem->getTaxAmount()); - $line[] = ['text' => $tax, 'feed' => 495, 'font' => 'bold', 'align' => 'right']; + return $drawItems; + } - $row_total = $order->formatPriceTxt($childItem->getRowTotal()); - $line[] = ['text' => $row_total, 'feed' => 565, 'font' => 'bold', 'align' => 'right']; + /** + * Draw sku parts + * + * @param DataObject $childItem + * @param array $lines + * @return array + */ + private function drawSkus(DataObject $childItem, array $lines): array + { + $index = array_key_last($lines); + if (!$childItem->getOrderItem()->getParentItem()) { + $text = []; + foreach ($this->string->split($this->getItem()->getSku(), 17) as $part) { + $text[] = $part; } + $lines[$index][] = ['text' => $text, 'feed' => 255]; + } + + return $lines; + } - $drawItems[$optionId]['lines'][] = $line; + /** + * Draw prices for bundle product children items + * + * @param DataObject $childItem + * @param array $lines + * @return array + */ + private function drawPrices(DataObject $childItem, array $lines): array + { + $index = array_key_last($lines); + if ($this->canShowPriceInfo($childItem)) { + $lines[$index][] = ['text' => $childItem->getQty() * 1, 'feed' => 435, 'align' => 'right']; + + $tax = $this->getOrder()->formatPriceTxt($childItem->getTaxAmount()); + $lines[$index][] = ['text' => $tax, 'feed' => 495, 'font' => 'bold', 'align' => 'right']; + + $item = $this->getItem(); + $this->_item = $childItem; + $feedPrice = 380; + $feedSubtotal = $feedPrice + 185; + foreach ($this->getItemPricesForDisplay() as $priceData) { + if (isset($priceData['label'])) { + // draw Price label + $lines[$index][] = ['text' => $priceData['label'], 'feed' => $feedPrice, 'align' => 'right']; + // draw Subtotal label + $lines[$index][] = ['text' => $priceData['label'], 'feed' => $feedSubtotal, 'align' => 'right']; + $index++; + } + // draw Price + $lines[$index][] = [ + 'text' => $priceData['price'], + 'feed' => $feedPrice, + 'font' => 'bold', + 'align' => 'right', + ]; + // draw Subtotal + $lines[$index][] = [ + 'text' => $priceData['subtotal'], + 'feed' => $feedSubtotal, + 'font' => 'bold', + 'align' => 'right', + ]; + $index++; + } + $this->_item = $item; } - // custom options - $options = $item->getOrderItem()->getProductOptions(); + return $lines; + } + + /** + * Draw bundle product custom options + * + * @param array $draw + * @return array + */ + private function drawCustomOptions(array $draw): array + { + $options = $this->getItem()->getOrderItem()->getProductOptions(); if ($options && isset($options['options'])) { foreach ($options['options'] as $option) { $lines = []; @@ -180,12 +246,10 @@ public function draw() $lines[][] = ['text' => $text, 'feed' => 40]; } - $drawItems[] = ['lines' => $lines, 'height' => 15]; + $draw[] = ['lines' => $lines, 'height' => 15]; } } - $page = $pdf->drawLineBlocks($page, $drawItems, ['table_header' => true]); - - $this->setPage($page); + return $draw; } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php new file mode 100644 index 0000000000000..e93d231383820 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php @@ -0,0 +1,352 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items; + +use Magento\Bundle\Model\Sales\Order\Pdf\Items\Invoice; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\DataObject; +use Magento\Framework\Filesystem; +use Magento\Framework\Filter\FilterManager; +use Magento\Framework\Model\Context; +use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\Stdlib\StringUtils; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Pdf\Invoice as InvoicePdf; +use Magento\Tax\Helper\Data; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Zend_Pdf_Page; + +/** + * Covers bundle order item invoice print logic + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class InvoiceTest extends TestCase +{ + /** + * @var Invoice|MockObject + */ + private $model; + + /** + * @var Data|MockObject + */ + private $taxDataMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $contextMock = $this->createMock(Context::class); + $registryMock = $this->createMock(Registry::class); + $this->taxDataMock = $this->createMock(Data::class); + $directoryMock = $this->createMock(Filesystem\Directory\Read::class); + $directoryMock->expects($this->any())->method('getAbsolutePath')->willReturn(''); + $filesystemMock = $this->createMock(Filesystem::class); + $filesystemMock->expects($this->any())->method('getDirectoryRead')->willReturn($directoryMock); + $filterManagerMock = $this->createMock(FilterManager::class); + $stringUtilsMock = $this->createMock(StringUtils::class); + $stringUtilsMock->expects($this->any())->method('split')->willReturnArgument(0); + $resourceMock = $this->createMock(AbstractResource::class); + $collectionMock = $this->createMock(AbstractDb::class); + $serializerMock = $this->createMock(Json::class); + + $this->model = $this->getMockBuilder(Invoice::class) + ->setConstructorArgs( + [ + $contextMock, + $registryMock, + $this->taxDataMock, + $filesystemMock, + $filterManagerMock, + $stringUtilsMock, + $serializerMock, + $resourceMock, + $collectionMock, + [], + ] + ) + ->onlyMethods( + [ + '_setFontRegular', + 'getChildren', + 'isShipmentSeparately', + 'isChildCalculated', + 'getValueHtml', + 'getSelectionAttributes', + ] + ) + ->getMock(); + } + + /** + * @dataProvider invoiceDataProvider + * @param array $expected + * @param string $method + */ + public function testDrawPrice(array $expected, string $method): void + { + $this->taxDataMock->expects($this->any())->method($method)->willReturn(true); + $pageMock = $this->createMock(Zend_Pdf_Page::class); + $this->model->setPage($pageMock); + $pdfMock = $this->createMock(InvoicePdf::class); + $pdfMock->expects($this->any())->method('drawLineBlocks')->with( + $pageMock, + $expected, + ['table_header' => true] + )->willReturn($pageMock); + $this->model->setPdf($pdfMock); + + $this->prepareModel(); + $this->model->draw(); + } + + /** + * @return array[] + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function invoiceDataProvider(): array + { + return [ + 'display_both' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Incl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Incl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesBothPrices', + ], + 'including_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceInclTax', + ], + 'excluding_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceExclTax', + ], + ]; + } + + /** + * Prepare invoice draw model for test execution + * + * @return void + */ + private function prepareModel(): void + { + $parentItem = new DataObject( + [ + 'sku' => 'bundle-simple', + 'name' => 'Bundle', + 'order_item' => new DataObject( + [ + 'product_options' => [], + ] + ), + ] + ); + $items = [ + new DataObject( + [ + 'name' => 'Simple1', + 'sku' => 'simple1', + 'price' => '10.00', + 'price_incl_tax' => '10.83', + 'row_total' => '20.00', + 'row_total_incl_tax' => '21.66', + 'qty' => '2', + 'tax_amount' => '1.66', + 'order_item' => new DataObject( + [ + 'parent_item' => $parentItem, + ] + ), + ] + ), + ]; + $orderMock = $this->createMock(Order::class); + + $this->model->expects($this->any())->method('getChildren')->willReturn($items); + $this->model->expects($this->any())->method('isShipmentSeparately')->willReturn(false); + $this->model->expects($this->any())->method('isChildCalculated')->willReturn(true); + $this->model->expects($this->any())->method('getValueHtml')->willReturn($items[0]->getName()); + $this->model->expects($this->any())->method('getSelectionAttributes')->willReturn( + ['option_id' => 1, 'option_label' => 'test option'] + ); + + $orderMock->expects($this->any())->method('formatPriceTxt')->willReturnArgument(0); + $this->model->setOrder($orderMock); + $this->model->setItem($parentItem); + } +} From 1ce3e1fe70b5c549ff519560dd7ada48f7a2034c Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Thu, 31 Dec 2020 16:36:31 +0200 Subject: [PATCH 115/242] MC-30127: Product Price is mismatch in invoice and invoice PDF magento for Bundle Product 2.2.1 --- .../Model/Sales/Order/Pdf/Items/Invoice.php | 5 +- .../Sales/Order/Pdf/Items/InvoiceTest.php | 216 ++---------- .../Order/Pdf/Items/InvoiceTestProvider.php | 329 ++++++++++++++++++ 3 files changed, 355 insertions(+), 195 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php index 26d0fd274014c..a7f0a70b45219 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php @@ -96,8 +96,8 @@ private function drawChildrenItems(): array $prevOptionId = ''; $drawItems = []; $optionId = 0; + $lines = []; foreach ($this->getChildren($this->getItem()) as $childItem) { - $lines = []; $index = array_key_last($lines) !== null ? array_key_last($lines) + 1 : 0; $attributes = $this->getSelectionAttributes($childItem); if (is_array($attributes)) { @@ -115,7 +115,6 @@ private function drawChildrenItems(): array 'feed' => 35, ]; - $drawItems[$optionId] = ['height' => 15]; $index++; $prevOptionId = $attributes['option_id']; } @@ -133,8 +132,8 @@ private function drawChildrenItems(): array $lines = $this->drawSkus($childItem, $lines); $lines = $this->drawPrices($childItem, $lines); - $drawItems[$optionId]['lines'] = $lines; } + $drawItems[$optionId]['lines'] = $lines; return $drawItems; } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php index e93d231383820..e5bf94241dbd9 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php @@ -88,7 +88,7 @@ protected function setUp(): void } /** - * @dataProvider invoiceDataProvider + * @dataProvider \Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items\InvoiceTestProvider::getData * @param array $expected * @param string $method */ @@ -109,195 +109,6 @@ public function testDrawPrice(array $expected, string $method): void $this->model->draw(); } - /** - * @return array[] - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function invoiceDataProvider(): array - { - return [ - 'display_both' => [ - 'expected' => [ - 1 => [ - 'height' => 15, - 'lines' => [ - [ - [ - 'text' => 'test option', - 'feed' => 35, - 'font' => 'italic', - - ], - ], - [ - [ - 'text' => 'Simple1', - 'feed' => 40, - ], - [ - 'text' => 2, - 'feed' => 435, - 'align' => 'right', - ], - [ - 'text' => 1.66, - 'feed' => 495, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => 'Excl. Tax:', - 'feed' => 380, - 'align' => 'right', - ], - [ - 'text' => 'Excl. Tax:', - 'feed' => 565, - 'align' => 'right', - ], - ], - [ - [ - 'text' => '10.00', - 'feed' => 380, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '20.00', - 'feed' => 565, - 'font' => 'bold', - 'align' => 'right', - ], - ], - [ - [ - 'text' => 'Incl. Tax:', - 'feed' => 380, - 'align' => 'right', - ], - [ - 'text' => 'Incl. Tax:', - 'feed' => 565, - 'align' => 'right', - ], - ], - [ - [ - 'text' => '10.83', - 'feed' => 380, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '21.66', - 'feed' => 565, - 'font' => 'bold', - 'align' => 'right', - ], - ], - ], - ], - ], - 'tax_mock_method' => 'displaySalesBothPrices', - ], - 'including_tax' => [ - 'expected' => [ - 1 => [ - 'height' => 15, - 'lines' => [ - [ - [ - 'text' => 'test option', - 'feed' => 35, - 'font' => 'italic', - - ], - ], - [ - [ - 'text' => 'Simple1', - 'feed' => 40, - ], - [ - 'text' => 2, - 'feed' => 435, - 'align' => 'right', - ], - [ - 'text' => 1.66, - 'feed' => 495, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '10.83', - 'feed' => 380, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '21.66', - 'feed' => 565, - 'font' => 'bold', - 'align' => 'right', - ], - ], - ], - ], - ], - 'tax_mock_method' => 'displaySalesPriceInclTax', - ], - 'excluding_tax' => [ - 'expected' => [ - 1 => [ - 'height' => 15, - 'lines' => [ - [ - [ - 'text' => 'test option', - 'feed' => 35, - 'font' => 'italic', - - ], - ], - [ - [ - 'text' => 'Simple1', - 'feed' => 40, - ], - [ - 'text' => 2, - 'feed' => 435, - 'align' => 'right', - ], - [ - 'text' => 1.66, - 'feed' => 495, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '10.00', - 'feed' => 380, - 'font' => 'bold', - 'align' => 'right', - ], - [ - 'text' => '20.00', - 'feed' => 565, - 'font' => 'bold', - 'align' => 'right', - ], - ], - ], - ], - ], - 'tax_mock_method' => 'displaySalesPriceExclTax', - ], - ]; - } - /** * Prepare invoice draw model for test execution * @@ -334,16 +145,37 @@ private function prepareModel(): void ), ] ), + new DataObject( + [ + 'name' => 'Simple2', + 'sku' => 'simple2', + 'price' => '5.00', + 'price_incl_tax' => '5.41', + 'row_total' => '10.00', + 'row_total_incl_tax' => '10.83', + 'qty' => '2', + 'tax_amount' => '0.83', + 'order_item' => new DataObject( + [ + 'parent_item' => $parentItem, + ] + ), + ] + ), ]; $orderMock = $this->createMock(Order::class); $this->model->expects($this->any())->method('getChildren')->willReturn($items); $this->model->expects($this->any())->method('isShipmentSeparately')->willReturn(false); $this->model->expects($this->any())->method('isChildCalculated')->willReturn(true); - $this->model->expects($this->any())->method('getValueHtml')->willReturn($items[0]->getName()); - $this->model->expects($this->any())->method('getSelectionAttributes')->willReturn( + $this->model->expects($this->at(2))->method('getSelectionAttributes')->willReturn( ['option_id' => 1, 'option_label' => 'test option'] ); + $this->model->expects($this->at(3))->method('getValueHtml')->willReturn($items[0]->getName()); + $this->model->expects($this->at(5))->method('getSelectionAttributes')->willReturn( + ['option_id' => 1, 'option_label' => 'second option'] + ); + $this->model->expects($this->at(6))->method('getValueHtml')->willReturn($items[1]->getName()); $orderMock->expects($this->any())->method('formatPriceTxt')->willReturnArgument(0); $this->model->setOrder($orderMock); diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php new file mode 100644 index 0000000000000..7de3d383d006e --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php @@ -0,0 +1,329 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items; + +/** + * Data provider class for InvoiceTest class + */ +class InvoiceTestProvider +{ + /** + * Returns invoice test variations data + * + * @return array[] + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function getData(): array + { + return [ + 'display_both' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Incl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Incl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '5.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Incl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Incl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '5.41', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesBothPrices', + ], + 'including_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '5.41', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceInclTax', + ], + 'excluding_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '5.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceExclTax', + ], + ]; + } +} From c0ab9d7cbc4e7836100a4ab701b740742e353018 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 31 Dec 2020 16:43:00 +0200 Subject: [PATCH 116/242] MC-40148: Create automated test for: "Set decimal Qty increment" --- .../Model/System/Config/Backend/QtyincrementsTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php index 4ca993129de76..8fcec1c02670d 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php @@ -16,6 +16,10 @@ /** * Checks that the qty increments config backend model is working correctly + * + * @see \Magento\CatalogInventory\Model\System\Config\Backend\Qtyincrements + * + * @magentoAppArea adminhtml */ class QtyincrementsTest extends TestCase { @@ -34,11 +38,11 @@ class QtyincrementsTest extends TestCase protected function setUp(): void { $this->objectManager = Bootstrap::getObjectManager(); - $this->backendFactory = $this->objectManager->create(BackendFactory::class); + $this->backendFactory = $this->objectManager->get(BackendFactory::class); $this->qtyIncrements = $this->backendFactory->create(Qtyincrements::class, [ 'data' => [ 'path' => Configuration::XML_PATH_QTY_INCREMENTS, - ] + ], ]); } From 3bc048d8528eff0993999c584725a59e4c21a12a Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 4 Jan 2021 12:07:38 +0200 Subject: [PATCH 117/242] refactored CancelOrdersInOrderSalesReportTest --- .../templates/widget/grid/extended.phtml | 5 +- .../Pricing/Price/BundleSelectionFactory.php | 5 +- .../Product/Form/Modifier/BundlePanelTest.php | 166 ++++++++++++ .../Product/Form/Modifier/BundlePanel.php | 17 +- .../catalog/category/widget/tree.phtml | 14 +- .../Model/Import/Product/Validator/Media.php | 2 +- .../Model/Quote/Item/QuantityValidator.php | 16 +- .../Initializer/QuantityValidatorTest.php | 49 +++- .../Pricing/Price/UpdateCatalogRulePrice.php | 68 +++++ .../CatalogRuleGraphQl/etc/graphql/di.xml | 12 + app/code/Magento/CatalogUrlRewrite/etc/di.xml | 8 + app/code/Magento/CmsUrlRewrite/etc/di.xml | 7 + ...vailableToConfigureDisabledProductTest.xml | 4 +- .../Controller/Adminhtml/Address/Viewfile.php | 180 +++++++++++++ .../Model/Address/AbstractAddress.php | 7 +- .../Magento/Customer/Model/FileProcessor.php | 7 +- .../Customer/Model/Metadata/Form/File.php | 20 +- .../StorefrontCustomerOrderShipmentPage.xml | 14 + .../Test/Unit/Model/FileProcessorTest.php | 22 +- .../Unit/Model/Metadata/Form/FileTest.php | 16 +- .../Model/Export/Address.php | 109 +++++--- .../Test/Unit/Model/Export/AddressTest.php | 89 +++---- .../Magento/Indexer/Model/ProcessManager.php | 5 +- .../Test/Unit/Model/ProcessManagerTest.php | 183 +++++++++++++ .../Controller/Hostedpro/ReturnAction.php | 6 +- .../Paypal/Model/Payflow/Service/Gateway.php | 68 ++++- .../Plugin/TransparentSessionChecker.php | 16 +- .../Model/Payflow/Service/GatewayTest.php | 177 +++++++++++-- .../AdminGoToOrdersReportPageActionGroup.xml | 18 ++ ...inCanceledOrdersInOrderSalesReportTest.xml | 101 ++++++++ .../CancelOrdersInOrderSalesReportTest.xml | 7 +- .../reports_report_review_product_grid.xml | 4 +- app/code/Magento/Review/Block/View.php | 3 +- ...inFilterProductReviewByNameActionGroup.xml | 20 ++ .../Test/Mftf/Data/ProductReviewData.xml | 16 ++ .../Section/AdminCreateNewReviewSection.xml | 5 + ...viewDateForReviewsByProductsReportTest.xml | 83 ++++++ .../Review/view/frontend/templates/view.phtml | 24 +- .../Model/Condition/AbstractCondition.php | 2 +- .../Model/Condition/AbstractConditionTest.php | 6 + .../Adminhtml/Order/AddressSave.php | 50 +++- .../Magento/Sales/Model/AdminOrder/Create.php | 43 ++- .../Model/Order/Creditmemo/Total/Tax.php | 244 ++++++++++++++---- .../Model/ResourceModel/Order/Invoice.php | 35 ++- ...ontOrderShipmentsQtyShippedActionGroup.xml | 24 ++ .../Sales/Test/Mftf/Data/CancelOrderData.xml | 17 ++ .../Test/Mftf/Metadata/CancelOrderMeta.xml | 17 ++ .../StorefrontSalesOrderShipmentSection.xml | 14 + ...ifyOrderShipmentForDecimalQuantityTest.xml | 104 ++++++++ .../Model/Order/Creditmemo/Total/TaxTest.php | 78 ++++-- .../ViewModel/Header/LogoPathResolver.php | 69 +++++ .../frontend/layout/sales_order_print.xml | 5 + .../layout/sales_order_printcreditmemo.xml | 5 + .../layout/sales_order_printinvoice.xml | 5 + .../layout/sales_order_printshipment.xml | 5 + .../shipment/items/renderer/default.phtml | 2 +- .../Magento/Theme/Block/Html/Header/Logo.php | 16 +- .../Test/Unit/Block/Html/Header/LogoTest.php | 7 +- .../Block/Html/Header/LogoPathResolver.php | 51 ++++ .../Html/Header/LogoPathResolverInterface.php | 21 ++ .../Theme/view/frontend/layout/default.xml | 6 +- .../Magento/UrlRewrite/Model/UrlRewrite.php | 168 +++++++++++- .../GraphQl/CatalogGraphQl/PriceRangeTest.php | 175 +++++++++++++ .../GraphQl/UrlRewrite/UrlResolverTest.php | 179 ++++++++++++- .../Quote/Api/GuestCartItemRepositoryTest.php | 2 +- .../Block/Widget/Grid/ExtendedTest.php | 56 +++- .../Bundle/Pricing/Price/FinalPriceTest.php | 72 ++++++ ...dle_product_with_tier_price_selections.php | 81 ++++++ ...ct_with_tier_price_selections_rollback.php | 33 +++ ...t_with_tier_prices_for_logged_in_group.php | 48 ++++ ...er_prices_for_logged_in_group_rollback.php | 10 + ...th_tier_prices_for_not_logged_in_group.php | 48 ++++ ...rices_for_not_logged_in_group_rollback.php | 10 + .../three_simple_products_with_tier_price.php | 68 +++++ ...mple_products_with_tier_price_rollback.php | 31 +++ .../Model/Export/ProductTest.php | 58 +++++ .../Model/Import/ProductTest.php | 82 ++++++ .../Model/Import/_files/import_media.csv | 2 +- ...port_media_additional_images_storeview.csv | 2 +- ...media_additional_images_with_wrong_url.csv | 2 + .../_files/import_media_existing_images.csv | 2 +- .../_files/import_media_hidden_images.csv | 4 +- ...import_with_json_and_markup_attributes.csv | 3 + ...ucts_to_import_with_non_existing_image.csv | 2 +- .../catalog_rule_25_customer_group_all.php | 39 +++ ...og_rule_25_customer_group_all_rollback.php | 35 +++ ...alog_rule_50_registered_customer_group.php | 39 +++ ..._50_registered_customer_group_rollback.php | 35 +++ .../Interception/PluginListGeneratorTest.php | 61 +++-- .../Controller/Hostedpro/ReturnActionTest.php | 54 ++++ .../Magento/Review/Block/ViewTest.php | 143 ++++++++++ .../_files/product_review_with_rating.php | 86 ++++++ .../product_review_with_rating_rollback.php | 11 + .../Sales/Block/Order/PrintOrder/LogoTest.php | 74 ++++++ .../DependenciesShowFrameworkCommandTest.php | 4 +- .../expected/framework-dependencies.csv | 2 +- lib/internal/Magento/Framework/File/Csv.php | 7 +- .../Framework/Filesystem/Driver/File.php | 7 +- .../Filesystem/Driver/StatefulFile.php | 2 +- .../Framework/Filesystem/DriverInterface.php | 2 +- .../Framework/Filesystem/File/Read.php | 2 +- .../Filesystem/File/ReadInterface.php | 2 +- .../Interception/PluginListGenerator.php | 4 +- pub/media/customer_address/.htaccess | 7 + 104 files changed, 3810 insertions(+), 343 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/Form/Modifier/BundlePanelTest.php create mode 100644 app/code/Magento/CatalogRuleGraphQl/Plugin/Pricing/Price/UpdateCatalogRulePrice.php create mode 100644 app/code/Magento/CatalogRuleGraphQl/etc/graphql/di.xml create mode 100644 app/code/Magento/Customer/Controller/Adminhtml/Address/Viewfile.php create mode 100644 app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerOrderShipmentPage.xml create mode 100644 app/code/Magento/Indexer/Test/Unit/Model/ProcessManagerTest.php create mode 100644 app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGoToOrdersReportPageActionGroup.xml create mode 100644 app/code/Magento/Reports/Test/Mftf/Test/AdminCanceledOrdersInOrderSalesReportTest.xml create mode 100644 app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFilterProductReviewByNameActionGroup.xml create mode 100644 app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontOrderShipmentsQtyShippedActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/CancelOrderData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Metadata/CancelOrderMeta.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/StorefrontSalesOrderShipmentSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml create mode 100644 app/code/Magento/Sales/ViewModel/Header/LogoPathResolver.php create mode 100644 app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolver.php create mode 100644 app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolverInterface.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogGraphQl/PriceRangeTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/Pricing/Price/FinalPriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections.php create mode 100644 dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_with_wrong_url.csv create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_json_and_markup_attributes.csv create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Paypal/Controller/Hostedpro/ReturnActionTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Review/Block/ViewTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating.php create mode 100644 dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Block/Order/PrintOrder/LogoTest.php create mode 100644 pub/media/customer_address/.htaccess diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml index d4aa14250837f..4bdee469e2fa4 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid/extended.phtml @@ -14,12 +14,13 @@ * getPagerVisibility() * getVarNamePage() */ -$numColumns = count($block->getColumns()); /** * @var \Magento\Backend\Block\Widget\Grid\Extended $block * @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */ +$numColumns = count($block->getColumns()); + ?> <?php if ($block->getCollection()): ?> <?php if ($block->canDisplayContainer()): ?> @@ -285,7 +286,9 @@ $numColumns = count($block->getColumns()); </table> </div> + <?php if ($block->canDisplayContainer()): ?> </div> + <?php endif; ?> <?php /** @var \Magento\Framework\Json\Helper\Data $jsonHelper */ $jsonHelper = $block->getData('jsonHelper'); diff --git a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php index a28d721cc9a4e..52a024dc9fac3 100644 --- a/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php +++ b/app/code/Magento/Bundle/Pricing/Price/BundleSelectionFactory.php @@ -52,9 +52,12 @@ public function create( $quantity, array $arguments = [] ) { + $quantity = $quantity ? (float)$quantity : 1.; + $selection->setQty($quantity); + $arguments['bundleProduct'] = $bundleProduct; $arguments['saleableItem'] = $selection; - $arguments['quantity'] = $quantity ? (float)$quantity : 1.; + $arguments['quantity'] = $quantity; return $this->objectManager->create(self::SELECTION_CLASS_DEFAULT, $arguments); } diff --git a/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/Form/Modifier/BundlePanelTest.php b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/Form/Modifier/BundlePanelTest.php new file mode 100644 index 0000000000000..51563d319dfc8 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/Form/Modifier/BundlePanelTest.php @@ -0,0 +1,166 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Ui\DataProvider\Product\Form\Modifier; + +use Magento\Bundle\Model\Product\Attribute\Source\Shipment\Type as ShipmentType; +use Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\BundlePanel; +use Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\BundlePrice; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Locator\LocatorInterface; +use Magento\Framework\Stdlib\ArrayManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\UrlInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Test for bundle panel + */ +class BundlePanelTest extends TestCase +{ + /** + * @var UrlInterface|MockObject + */ + private $urlBuilder; + + /** + * @var ShipmentType|MockObject + */ + private $shipmentType; + + /** + * @var LocatorInterface|MockObject + */ + private $locatorMock; + + /** + * @var ProductInterface|MockObject + */ + private $productMock; + + /** + * @var ArrayManager|MockObject + */ + private $arrayManagerMock; + + /** + * @var BundlePanel + */ + private $bundlePanelModel; + + /** + * @return void + */ + protected function setUp(): void + { + $this->objectManager = new ObjectManager($this); + $this->arrayManagerMock = $this->getMockBuilder(ArrayManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->arrayManagerMock->expects($this->any()) + ->method('get') + ->willReturn([]); + $this->urlBuilder = $this->getMockBuilder(UrlInterface::class) + ->getMockForAbstractClass(); + $this->shipmentType = $this->getMockBuilder(ShipmentType::class) + ->getMockForAbstractClass(); + $this->productMock = $this->getMockBuilder(ProductInterface::class) + ->addMethods(['getStoreId']) + ->getMockForAbstractClass(); + $this->productMock->method('getId') + ->willReturn(true); + $this->productMock->method('getStoreId') + ->willReturn(0); + $this->locatorMock = $this->getMockBuilder(LocatorInterface::class) + ->onlyMethods(['getProduct']) + ->getMockForAbstractClass(); + $this->locatorMock->method('getProduct') + ->willReturn($this->productMock); + + $this->bundlePanelModel = $this->objectManager->getObject( + BundlePanel::class, + [ + 'locator' => $this->locatorMock, + 'urlBuilder' => $this->urlBuilder, + 'shipmentType' => $this->shipmentType, + 'arrayManager' => $this->arrayManagerMock, + ] + ); + } + + /** + * Test for modify meta + * + * @param string $shipmentTypePath + * @param string $dataScope + * + * @return void + * @dataProvider getDataModifyMeta + */ + public function testModifyMeta(string $shipmentTypePath, string $dataScope): void + { + $sourceMeta = [ + 'bundle-items' => [ + 'children' => [ + BundlePrice::CODE_PRICE_TYPE => [] + ] + ] + ]; + $this->arrayManagerMock->method('findPath') + ->willReturnMap( + [ + [ + BundlePanel::CODE_SHIPMENT_TYPE, + [], + null, + 'children', + ArrayManager::DEFAULT_PATH_DELIMITER, + $shipmentTypePath + ], + ] + ); + $this->arrayManagerMock->method('merge') + ->willReturn([]); + $this->arrayManagerMock->method('remove') + ->willReturn([]); + $this->arrayManagerMock->method('set') + ->willReturn([]); + $this->arrayManagerMock->expects($this->at(12)) + ->method('merge') + ->with( + $shipmentTypePath . BundlePanel::META_CONFIG_PATH, + [], + [ + 'dataScope' => $dataScope, + 'validation' => [ + 'required-entry' => false + ] + ] + ); + $this->bundlePanelModel->modifyMeta($sourceMeta); + } + + /** + * Data provider for modify meta test + * + * @return string[][] + */ + public function getDataModifyMeta(): array + { + return [ + [ + 'bundle-items/children', + 'data.product.shipment_type' + ], + [ + 'someAttrGroup/children', + 'shipment_type' + ], + ]; + } +} diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php index 5ff9e674acad9..01b113def9243 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php @@ -252,16 +252,19 @@ public function modifyData(array $data) */ private function modifyShipmentType(array $meta) { + $actualPath = $this->arrayManager->findPath( + static::CODE_SHIPMENT_TYPE, + $meta, + null, + 'children' + ); + $meta = $this->arrayManager->merge( - $this->arrayManager->findPath( - static::CODE_SHIPMENT_TYPE, - $meta, - null, - 'children' - ) . static::META_CONFIG_PATH, + $actualPath . static::META_CONFIG_PATH, $meta, [ - 'dataScope' => 'data.product.shipment_type', + 'dataScope' => stripos($actualPath, self::CODE_BUNDLE_DATA) === 0 + ? 'data.product.shipment_type' : 'shipment_type', 'validation' => [ 'required-entry' => false ] diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml index 6c92ddcf36243..cf64c57c720b7 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml @@ -77,6 +77,16 @@ $scriptString .= <<<script dataUrl: '{$block->escapeJs($block->escapeUrl($block->getLoadTreeUrl()))}' }); + categoryLoader.processResponse = function (response, parent, callback) { + var config = JSON.parse(response.responseText); + + this.buildCategoryTree(parent, config); + + if (typeof callback == "function") { + callback(this, parent); + } + }; + categoryLoader.buildCategoryTree = function(parent, config) { if (!config) return null; @@ -164,8 +174,10 @@ $scriptString .= <<<script }; categoryLoader.on("beforeload", function(treeLoader, node) { - $('{$block->escapeJs($_divId)}').fire('category:beforeLoad', {treeLoader:treeLoader}); treeLoader.baseParams.id = node.attributes.id; + treeLoader.baseParams.store = node.attributes.store; + treeLoader.baseParams.form_key = FORM_KEY; + $('{$block->escapeJs($_divId)}').fire('category:beforeLoad', {treeLoader:treeLoader}); }); tree{$block->escapeJs($block->getId())} = new Ext.tree.TreePanel.Enhanced('{$block->escapeJs($_divId)}', { diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php index d1fe1eee80e19..8df5afce568f1 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php @@ -114,8 +114,8 @@ public function isValid($value) ] ); $valid = false; + break; } - break; } } return $valid; diff --git a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php index 317a573a653e9..12a48caf62414 100644 --- a/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Quote/Item/QuantityValidator.php @@ -157,11 +157,17 @@ public function validate(Observer $observer) if ($stockStatus->getStockStatus() === Stock::STOCK_OUT_OF_STOCK || $parentStockStatus && $parentStockStatus->getStockStatus() == Stock::STOCK_OUT_OF_STOCK ) { - $quoteItem->addErrorInfo( - 'cataloginventory', - Data::ERROR_QTY, - __('This product is out of stock.') - ); + $hasError = $quoteItem->getStockStateResult() + ? $quoteItem->getStockStateResult()->getHasError() : false; + if (!$hasError) { + $quoteItem->addErrorInfo( + 'cataloginventory', + Data::ERROR_QTY, + __('This product is out of stock.') + ); + } else { + $quoteItem->addErrorInfo(null, Data::ERROR_QTY); + } $quoteItem->getQuote()->addErrorInfo( 'stock', 'cataloginventory', diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/QuantityValidatorTest.php index edc22a008c554..36b9fd0adeb81 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/QuantityValidatorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Quote/Item/QuantityValidator/Initializer/QuantityValidatorTest.php @@ -153,7 +153,7 @@ protected function setUp(): void ->getMock(); $this->storeMock = $this->createMock(Store::class); $this->quoteItemMock = $this->getMockBuilder(Item::class) - ->addMethods(['getProductId', 'getHasError']) + ->addMethods(['getProductId', 'getHasError', 'getStockStateResult']) ->onlyMethods( [ 'getQuote', @@ -460,6 +460,53 @@ public function testException() $this->quantityValidator->validate($this->observerMock); } + /** + * This tests the scenario when the error is in the quote item already + * + * @return void + */ + public function testValidateOutStockWithAlreadyErrorInQuoteItem(): void + { + $this->createInitialStub(1); + $resultMock = $this->getMockBuilder(DataObject::class) + ->addMethods(['checkQtyIncrements', 'getMessage', 'getQuoteMessage', 'getHasError']) + ->getMock(); + $resultMock->method('getHasError') + ->willReturn(true); + $this->stockRegistryMock->method('getStockItem') + ->willReturn($this->stockItemMock); + $this->stockRegistryMock->expects($this->at(1)) + ->method('getStockStatus') + ->willReturn($this->stockStatusMock); + $this->quoteItemMock->method('getParentItem') + ->willReturn($this->parentItemMock); + $this->quoteItemMock->method('getStockStateResult') + ->willReturn($resultMock); + $this->stockRegistryMock->expects($this->at(2)) + ->method('getStockStatus') + ->willReturn($this->parentStockItemMock); + $this->parentStockItemMock->method('getStockStatus') + ->willReturn(0); + $this->stockStatusMock->expects($this->atLeastOnce()) + ->method('getStockStatus') + ->willReturn(1); + $this->quoteItemMock->expects($this->once()) + ->method('addErrorInfo') + ->with( + null, + Data::ERROR_QTY, + ); + $this->quoteMock->expects($this->once()) + ->method('addErrorInfo') + ->with( + 'stock', + 'cataloginventory', + Data::ERROR_QTY, + __('Some of the products are out of stock.') + ); + $this->quantityValidator->validate($this->observerMock); + } + /** * @param $qty * @param $hasError diff --git a/app/code/Magento/CatalogRuleGraphQl/Plugin/Pricing/Price/UpdateCatalogRulePrice.php b/app/code/Magento/CatalogRuleGraphQl/Plugin/Pricing/Price/UpdateCatalogRulePrice.php new file mode 100644 index 0000000000000..61b9f70c49f04 --- /dev/null +++ b/app/code/Magento/CatalogRuleGraphQl/Plugin/Pricing/Price/UpdateCatalogRulePrice.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogRuleGraphQl\Plugin\Pricing\Price; + +use Magento\CatalogRule\Model\ResourceModel\Rule; +use Magento\CatalogRule\Pricing\Price\CatalogRulePrice; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; + +/** + * Class UpdateCatalogRulePrice + * + * Plugin to update catalog rule price based on customer group id + */ +class UpdateCatalogRulePrice +{ + /** + * @var TimezoneInterface + */ + private $dateTime; + + /** + * @var Rule + */ + private $ruleResource; + + /** + * @param TimezoneInterface $dateTime + * @param Rule $ruleResource + */ + public function __construct( + TimezoneInterface $dateTime, + Rule $ruleResource + ) { + $this->dateTime = $dateTime; + $this->ruleResource = $ruleResource; + } + + /** + * Returns catalog rule value for logged in customer group + * + * @param CatalogRulePrice $catalogRulePrice + * @param float|boolean $value + * @return float|boolean + */ + public function afterGetValue( + CatalogRulePrice $catalogRulePrice, + $value + ) { + $product = $catalogRulePrice->getProduct(); + if ($product && $product->getCustomerGroupId()) { + $store = $product->getStore(); + $value = $this->ruleResource->getRulePrice( + $this->dateTime->scopeDate($store->getId()), + $store->getWebsiteId(), + $product->getCustomerGroupId(), + $product->getId() + ); + $value = $value ? (float) $value : false; + } + + return $value; + } +} diff --git a/app/code/Magento/CatalogRuleGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogRuleGraphQl/etc/graphql/di.xml new file mode 100644 index 0000000000000..571783edece6c --- /dev/null +++ b/app/code/Magento/CatalogRuleGraphQl/etc/graphql/di.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\CatalogRule\Pricing\Price\CatalogRulePrice"> + <plugin name="update_catalog_rule_price_for_logged_in_customer_group" type="Magento\CatalogRuleGraphQl\Plugin\Pricing\Price\UpdateCatalogRulePrice"/> + </type> +</config> diff --git a/app/code/Magento/CatalogUrlRewrite/etc/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/di.xml index d22816243f64c..533693692cd5c 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/di.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/di.xml @@ -59,6 +59,14 @@ </argument> </arguments> </type> + <type name="Magento\UrlRewrite\Model\UrlRewrite"> + <arguments> + <argument name="entityToCacheTagMap" xsi:type="array"> + <item name="product" xsi:type="const">Magento\Catalog\Model\Product::CACHE_TAG</item> + <item name="category" xsi:type="const">Magento\Catalog\Model\Category::CACHE_TAG</item> + </argument> + </arguments> + </type> <type name="Magento\Eav\Model\Config"> <arguments> <argument name="attributesForPreload" xsi:type="array"> diff --git a/app/code/Magento/CmsUrlRewrite/etc/di.xml b/app/code/Magento/CmsUrlRewrite/etc/di.xml index 497d7a175842d..0463bf5b696c5 100644 --- a/app/code/Magento/CmsUrlRewrite/etc/di.xml +++ b/app/code/Magento/CmsUrlRewrite/etc/di.xml @@ -9,4 +9,11 @@ <type name="Magento\Cms\Model\ResourceModel\Page"> <plugin name="cms_url_rewrite_plugin" type="Magento\CmsUrlRewrite\Plugin\Cms\Model\ResourceModel\Page"/> </type> + <type name="Magento\UrlRewrite\Model\UrlRewrite"> + <arguments> + <argument name="entityToCacheTagMap" xsi:type="array"> + <item name="cms-page" xsi:type="const">Magento\Cms\Model\Page::CACHE_TAG</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml index e0dae94f13150..b75dd590dbbf1 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml +++ b/app/code/Magento/ConfigurableProduct/Test/Mftf/Test/NoOptionAvailableToConfigureDisabledProductTest.xml @@ -125,7 +125,7 @@ <actionGroup ref="AdminSetStockStatusActionGroup" stepKey="outOfStockStatus"> <argument name="stockStatus" value="Out of Stock"/> </actionGroup> - + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveSecondProductForm"/> <!-- Go to created customer page --> <comment userInput="Go to created customer page" stepKey="goToCreatedCustomerPage"/> @@ -158,7 +158,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickToAddProductToOrder"/> <waitForPageLoad stepKey="waitForNewOrderPageLoad"/> - <see userInput="This product is out of stock." stepKey="seeTheErrorMessageDisplayed"/> + <see userInput="There are no source items with the in stock status" stepKey="seeTheErrorMessageDisplayed"/> <actionGroup ref="NavigateToNewOrderPageExistingCustomerActionGroup" stepKey="createNewOrderThirdTime"> <argument name="customer" value="$createCustomer$"/> diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Address/Viewfile.php b/app/code/Magento/Customer/Controller/Adminhtml/Address/Viewfile.php new file mode 100644 index 0000000000000..a8cad14c23a72 --- /dev/null +++ b/app/code/Magento/Customer/Controller/Adminhtml/Address/Viewfile.php @@ -0,0 +1,180 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Controller\Adminhtml\Address; + +use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Controller\Result\RawFactory; +use Magento\Framework\Url\DecoderInterface; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Filesystem; +use Magento\Framework\Controller\Result\Raw; +use Magento\MediaStorage\Helper\File\Storage; +use Magento\Framework\App\Response\Http\FileFactory; +use Magento\Framework\Filesystem\Io\File as IoFile; +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Backend\App\Action; + +/** + * Class Viewfile serves to show file or image by file/image name provided in request parameters. + */ +class Viewfile extends Action implements HttpGetActionInterface +{ + /** + * Authorization level of a basic admin session + */ + const ADMIN_RESOURCE = 'Magento_Customer::manage'; + + /** + * @var RawFactory + */ + private $resultRawFactory; + + /** + * @var DecoderInterface + */ + private $urlDecoder; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var Storage + */ + private $storage; + + /** + * @var FileFactory + */ + private $fileFactory; + + /** + * @var IoFile + */ + private $ioFile; + + /** + * @param Context $context + * @param FileFactory $fileFactory + * @param RawFactory $resultRawFactory + * @param DecoderInterface $urlDecoder + * @param Filesystem $filesystem + * @param Storage $storage + * @param IoFile $ioFile + */ + public function __construct( + Context $context, + FileFactory $fileFactory, + RawFactory $resultRawFactory, + DecoderInterface $urlDecoder, + Filesystem $filesystem, + Storage $storage, + IoFile $ioFile + ) { + parent::__construct($context); + $this->resultRawFactory = $resultRawFactory; + $this->urlDecoder = $urlDecoder; + $this->filesystem = $filesystem; + $this->storage = $storage; + $this->fileFactory = $fileFactory; + $this->ioFile = $ioFile; + } + + /** + * Customer address view file action + * + * @return ResultInterface|void + * @throws NotFoundException + */ + public function execute() + { + list($file, $plain) = $this->getFileParams(); + + $directory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA); + $fileName = AddressMetadataInterface::ENTITY_TYPE_ADDRESS . DIRECTORY_SEPARATOR . + ltrim($file, DIRECTORY_SEPARATOR); + $path = $directory->getAbsolutePath($fileName); + if (mb_strpos($path, '..') !== false + || (!$directory->isFile($fileName) && !$this->storage->processStorageFile($path)) + ) { + throw new NotFoundException(__('Page not found.')); + } + + $pathInfo = $this->ioFile->getPathInfo($path); + if ($plain) { + $extension = $pathInfo['extension']; + switch (strtolower($extension)) { + case 'gif': + $contentType = 'image/gif'; + break; + case 'jpg': + $contentType = 'image/jpeg'; + break; + case 'png': + $contentType = 'image/png'; + break; + default: + $contentType = 'application/octet-stream'; + break; + } + $stat = $directory->stat($fileName); + $contentLength = $stat['size']; + $contentModify = $stat['mtime']; + + /** @var Raw $resultRaw */ + $resultRaw = $this->resultRawFactory->create(); + $resultRaw->setHttpResponseCode(200) + ->setHeader('Pragma', 'public', true) + ->setHeader('Content-type', $contentType, true) + ->setHeader('Content-Length', $contentLength) + ->setHeader('Last-Modified', date('r', $contentModify)); + $resultRaw->setContents($directory->readFile($fileName)); + + return $resultRaw; + } else { + $name = $pathInfo['basename']; + $this->fileFactory->create( + $name, + ['type' => 'filename', 'value' => $fileName], + DirectoryList::MEDIA + ); + } + } + + /** + * Get parameters from request. + * + * @return array + * @throws NotFoundException + */ + private function getFileParams() : array + { + $file = null; + $plain = false; + if ($this->getRequest()->getParam('file')) { + // download file + $file = $this->urlDecoder->decode( + $this->getRequest()->getParam('file') + ); + } elseif ($this->getRequest()->getParam('image')) { + // show plain image + $file = $this->urlDecoder->decode( + $this->getRequest()->getParam('image') + ); + $plain = true; + } else { + throw new NotFoundException(__('Page not found.')); + } + + return [$file, $plain]; + } +} diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 8421fc92f8c4a..d1364dc0aeba6 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -331,10 +331,11 @@ protected function _implodeArrayValues($value) return ''; } - $isScalar = false; + $isScalar = true; foreach ($value as $val) { - if (is_scalar($val)) { - $isScalar = true; + if (!is_scalar($val)) { + $isScalar = false; + break; } } if ($isScalar) { diff --git a/app/code/Magento/Customer/Model/FileProcessor.php b/app/code/Magento/Customer/Model/FileProcessor.php index 02bfe78be535c..59e2d5fb2b577 100644 --- a/app/code/Magento/Customer/Model/FileProcessor.php +++ b/app/code/Magento/Customer/Model/FileProcessor.php @@ -158,9 +158,10 @@ public function getViewUrl($filePath, $type) $viewUrl = ''; if ($this->entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { - $filePath = $this->entityTypeCode . '/' . ltrim($filePath, '/'); - $viewUrl = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]) - . $this->mediaDirectory->getRelativePath($filePath); + $viewUrl = $this->urlBuilder->getUrl( + 'customer/address/viewfile', + [$type => $this->urlEncoder->encode(ltrim($filePath, '/'))] + ); } if ($this->entityTypeCode == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { diff --git a/app/code/Magento/Customer/Model/Metadata/Form/File.php b/app/code/Magento/Customer/Model/Metadata/Form/File.php index 17cfc0325ef41..1add044c50c9e 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/File.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/File.php @@ -100,6 +100,7 @@ public function __construct( FileProcessorFactory $fileProcessorFactory = null, IoFile $ioFile = null ) { + $value = $this->prepareFileValue($value); parent::__construct($localeDate, $logger, $attribute, $localeResolver, $value, $entityTypeCode, $isAjax); $this->urlEncoder = $urlEncoder; $this->_fileValidator = $fileValidator; @@ -302,11 +303,11 @@ public function validateValue($value) public function compactValue($value) { if ($this->getIsAjaxRequest()) { - return $this; + return ''; } // Remove outdated file (in the case of file uploader UI component) - if (empty($value) && !empty($this->_value)) { + if (!empty($this->_value) && !empty($value['delete'])) { $this->fileProcessor->removeUploadedFile($this->_value); return $value; } @@ -420,4 +421,19 @@ protected function getFileProcessor() { return $this->fileProcessor; } + + /** + * Prepare File value. + * + * @param array|string $value + * @return array|string + */ + private function prepareFileValue($value) + { + if (is_array($value) && isset($value['value'])) { + $value = $value['value']; + } + + return $value; + } } diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerOrderShipmentPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerOrderShipmentPage.xml new file mode 100644 index 0000000000000..da41e6ada79a0 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerOrderShipmentPage.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="StorefrontCustomerOrderShipmentPage" url="sales/order/shipment/order_id/{{var1}}" area="storefront" module="Magento_Customer" parameterized="true"> + <section name="StorefrontCustomerOrderSection"/> + </page> +</pages> diff --git a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php index 7a0522f6476f2..fb775ce78bbbc 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php @@ -162,22 +162,22 @@ public function testGetViewUrlCustomer() public function testGetViewUrlCustomerAddress() { $filePath = 'filename.ext1'; + $encodedFilePath = 'encodedfilenameext1'; - $baseUrl = 'baseUrl'; - $relativeUrl = 'relativeUrl'; + $fileUrl = 'fileUrl'; - $this->urlBuilder->expects($this->once()) - ->method('getBaseUrl') - ->with(['_type' => UrlInterface::URL_TYPE_MEDIA]) - ->willReturn($baseUrl); + $this->urlEncoder->expects($this->once()) + ->method('encode') + ->with($filePath) + ->willReturn($encodedFilePath); - $this->mediaDirectory->expects($this->once()) - ->method('getRelativePath') - ->with(AddressMetadataInterface::ENTITY_TYPE_ADDRESS . '/' . $filePath) - ->willReturn($relativeUrl); + $this->urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('customer/address/viewfile', ['image' => $encodedFilePath]) + ->willReturn($fileUrl); $model = $this->getModel(AddressMetadataInterface::ENTITY_TYPE_ADDRESS); - $this->assertEquals($baseUrl . $relativeUrl, $model->getViewUrl($filePath, 'image')); + $this->assertEquals($fileUrl, $model->getViewUrl($filePath, 'image')); } public function testRemoveUploadedFile() diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/FileTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/FileTest.php index 3c5016df230f9..b0e9805bb3d2a 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/FileTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/FileTest.php @@ -347,7 +347,7 @@ public function testCompactValueIsAjax() ] ); - $this->assertSame($model, $model->compactValue('aValue')); + $this->assertSame('', $model->compactValue('aValue')); } public function testCompactValueNoDelete() @@ -362,12 +362,12 @@ public function testCompactValueNoDelete() ] ); - $this->fileProcessorMock->expects($this->once()) + $this->fileProcessorMock->expects($this->any()) ->method('removeUploadedFile') ->with('value') ->willReturnSelf(); - $this->assertSame([], $model->compactValue([])); + $this->assertSame('value', $model->compactValue([])); } public function testCompactValueDelete() @@ -377,11 +377,11 @@ public function testCompactValueDelete() $mediaDirMock = $this->getMockForAbstractClass( \Magento\Framework\Filesystem\Directory\WriteInterface::class ); - $mediaDirMock->expects($this->once()) + $mediaDirMock->expects($this->any()) ->method('delete') ->with(self::ENTITY_TYPE . '/' . 'value'); - $this->fileSystemMock->expects($this->once()) + $this->fileSystemMock->expects($this->any()) ->method('getDirectoryWrite') ->with(DirectoryList::MEDIA) ->will($this->returnValue($mediaDirMock)); @@ -394,7 +394,7 @@ public function testCompactValueDelete() ] ); - $this->assertSame('', $model->compactValue(['delete' => true])); + $this->assertIsArray($model->compactValue(['delete' => true])); } public function testCompactValueTmpFile() @@ -589,12 +589,12 @@ public function testCompactValueRemoveUiComponentValue() ] ); - $this->fileProcessorMock->expects($this->once()) + $this->fileProcessorMock->expects($this->any()) ->method('removeUploadedFile') ->with($value) ->willReturnSelf(); - $this->assertEquals([], $model->compactValue([])); + $this->assertEquals($value, $model->compactValue([])); } public function testCompactValueNoAction() diff --git a/app/code/Magento/CustomerImportExport/Model/Export/Address.php b/app/code/Magento/CustomerImportExport/Model/Export/Address.php index 03ce884a44d20..a2d38767432d9 100644 --- a/app/code/Magento/CustomerImportExport/Model/Export/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Export/Address.php @@ -5,6 +5,17 @@ */ namespace Magento\CustomerImportExport\Model\Export; +use Magento\Customer\Model\ResourceModel\Address\Collection; +use Magento\Customer\Model\ResourceModel\Address\CollectionFactory; +use Magento\Eav\Model\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\DB\Select; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\ImportExport\Model\Export\Entity\AbstractEav; +use Magento\ImportExport\Model\Export\Factory; +use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory; +use Magento\Store\Model\StoreManagerInterface; + /** * Customer address export * @@ -13,7 +24,7 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ -class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav +class Address extends AbstractEav { /**#@+ * Permanent column names @@ -93,7 +104,7 @@ class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav /** * Customer addresses collection * - * @var \Magento\Customer\Model\ResourceModel\Address\Collection + * @var Collection */ protected $_addressCollection; @@ -118,31 +129,31 @@ class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav * * @var array */ - protected $_customers = []; + protected $_customers; /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory - * @param \Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory $resourceColFactory - * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate - * @param \Magento\Eav\Model\Config $eavConfig + * @param ScopeConfigInterface $scopeConfig + * @param StoreManagerInterface $storeManager + * @param Factory $collectionFactory + * @param CollectionByPagesIteratorFactory $resourceColFactory + * @param TimezoneInterface $localeDate + * @param Config $eavConfig * @param \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $customerColFactory - * @param \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory - * @param \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressColFactory + * @param CustomerFactory $eavCustomerFactory + * @param CollectionFactory $addressColFactory * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\ImportExport\Model\Export\Factory $collectionFactory, - \Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory $resourceColFactory, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Eav\Model\Config $eavConfig, + ScopeConfigInterface $scopeConfig, + StoreManagerInterface $storeManager, + Factory $collectionFactory, + CollectionByPagesIteratorFactory $resourceColFactory, + TimezoneInterface $localeDate, + Config $eavConfig, \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $customerColFactory, - \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory, - \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressColFactory, + CustomerFactory $eavCustomerFactory, + CollectionFactory $addressColFactory, array $data = [] ) { parent::__construct( @@ -178,19 +189,20 @@ public function __construct( */ protected function _initCustomers() { - if (empty($this->_customers)) { + if ($this->_customers === null) { + $this->_customers = []; // add customer default addresses column name to customer attribute mapping array $this->_customerCollection->addAttributeToSelect(self::$_defaultAddressAttributeMapping); // filter customer collection $this->_customerCollection = $this->_customerEntity->filterEntityCollection($this->_customerCollection); - $customers = []; - $addCustomer = function (\Magento\Customer\Model\Customer $customer) use (&$customers) { - $customers[$customer->getId()] = $customer->getData(); - }; + $selectIds = $this->_customerCollection->getAllIdsSql(); + $this->_customerCollection->setPageSize($this->_pageSize); + $pageCount = $this->_customerCollection->getLastPageNumber(); - $this->_byPagesIterator->iterate($this->_customerCollection, $this->_pageSize, [$addCustomer]); - $this->_customers = $customers; + for ($pageNum = 1; $pageNum <= $pageCount; $pageNum++) { + $this->_customers += $this->loadCustomerData($selectIds, $pageNum); + } } return $this; @@ -211,7 +223,7 @@ protected function _getHeaderColumns() /** * Get customers collection * - * @return \Magento\Customer\Model\ResourceModel\Address\Collection + * @return Collection */ protected function _getEntityCollection() { @@ -227,7 +239,7 @@ public function export() { // skip and filter by customer address attributes $this->_prepareEntityCollection($this->_getEntityCollection()); - $this->_getEntityCollection()->setCustomerFilter(array_keys($this->_customers)); + $this->_getEntityCollection()->setCustomerFilter(array_keys($this->getCustomers())); // prepare headers $this->getWriter()->setHeaderCols($this->_getHeaderColumns()); @@ -248,7 +260,7 @@ public function exportItem($item) $row = $this->_addAttributeValuesToRow($item); /** @var $customer \Magento\Customer\Model\Customer */ - $customer = $this->_customers[$item->getParentId()]; + $customer = $this->getCustomers()[$item->getParentId()]; // Fill row with default address attributes values foreach (self::$_defaultAddressAttributeMapping as $columnName => $attributeCode) { @@ -274,10 +286,8 @@ public function exportItem($item) */ public function setParameters(array $parameters) { - // push filters from post into export customer model + // push filters from post into export customer model $this->_customerEntity->setParameters($parameters); - $this->_initCustomers(); - return parent::setParameters($parameters); } @@ -290,4 +300,39 @@ public function getEntityTypeCode() { return $this->getAttributeCollection()->getEntityTypeCode(); } + + /** + * Get Customers Data + * + * @return array + */ + private function getCustomers(): array + { + $this->_initCustomers(); + return $this->_customers; + } + + /** + * Load Customers Data + * + * @param Select $selectIds + * @param int $pageNum + * @return array + */ + private function loadCustomerData(Select $selectIds, int $pageNum = 0): array + { + $select = $this->_customerCollection->getConnection()->select(); + $select->from( + ['customer' => $this->_customerCollection->getTable('customer_entity')], + ['entity_id', 'email', 'store_id', 'website_id', 'default_billing', 'default_shipping'] + )->where( + 'customer.entity_id IN (?)', $selectIds + ); + + if ($pageNum > 0) { + $select->limitPage($pageNum, $this->_pageSize); + } + + return $this->_customerCollection->getConnection()->fetchAssoc($select); + } } diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php index f40d71d2efa7c..2d8c105d2b29c 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php @@ -7,10 +7,7 @@ namespace Magento\CustomerImportExport\Test\Unit\Model\Export; -use Magento\Customer\Model\AddressFactory; -use Magento\Customer\Model\Config\Share; -use Magento\Customer\Model\GroupFactory; -use Magento\Customer\Model\ResourceModel\Customer; +use Magento\Customer\Model\ResourceModel\Customer\Collection as CustomerCollection; use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory; use Magento\CustomerImportExport\Model\Export\Address; use Magento\CustomerImportExport\Model\Export\CustomerFactory; @@ -19,9 +16,10 @@ use Magento\Eav\Model\Entity\TypeFactory; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Data\Collection; -use Magento\Framework\Data\Collection\AbstractDb; use Magento\Framework\Data\Collection\EntityFactory; use Magento\Framework\DataObject; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Select; use Magento\Framework\Model\AbstractModel; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -30,7 +28,6 @@ use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManager; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; /** @@ -82,7 +79,7 @@ class AddressTest extends TestCase /** * ObjectManager helper * - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var ObjectManager */ protected $_objectManager; @@ -93,6 +90,9 @@ class AddressTest extends TestCase */ protected $_model; + /** + * @inheritdoc + */ protected function setUp(): void { $storeManager = $this->createMock(StoreManager::class); @@ -119,6 +119,9 @@ protected function setUp(): void ); } + /** + * @inheritdoc + */ protected function tearDown(): void { unset($this->_model); @@ -132,8 +135,9 @@ protected function tearDown(): void */ protected function _getModelDependencies() { - $translator = $this->createMock(\stdClass::class); + $pageSize = 1; + $translator = $this->createMock(\stdClass::class); $entityFactory = $this->createMock(EntityFactory::class); /** @var Collection|TestCase $attributeCollection */ @@ -167,34 +171,35 @@ protected function _getModelDependencies() $attributeCollection->addItem($attribute); } - $byPagesIterator = $this->getMockBuilder(\stdClass::class)->addMethods(['iterate']) - ->disableOriginalConstructor() - ->getMock(); - $byPagesIterator->expects( - $this->once() - )->method( - 'iterate' - )->willReturnCallback( - [$this, 'iterate'] - ); - - $customerCollection = $this->getMockBuilder(AbstractDb::class) - ->setMethods(['addAttributeToSelect']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); + $connection = $this->createMock(AdapterInterface::class); + $customerCollection = $this->createMock(CustomerCollection::class); + $customerCollection->method('getConnection')->willReturn($connection); + $customerCollection->expects($this->once())->method('setPageSize')->with($pageSize); + $customerCollection->method('getLastPageNumber')->willReturn(1); + $allIdsSelect = $this->createMock(Select::class); + $customerCollection->method('getAllIdsSql')->willReturn($allIdsSelect); + + $customerSelect = $this->createMock(Select::class); + $customerSelect->method('from')->willReturnSelf(); + $customerSelect->expects($this->once()) + ->method('where') + ->with('customer.entity_id IN (?)', $allIdsSelect) + ->willReturnSelf(); + $customerSelect->expects($this->once())->method('limitPage')->with(1, $pageSize); + $connection->method('select')->willReturn($customerSelect); + $connection->method('fetchAssoc')->with($customerSelect)->willReturn([1 => $this->_customerData]); $customerEntity = $this->getMockBuilder(\stdClass::class) ->addMethods(['filterEntityCollection', 'setParameters']) ->disableOriginalConstructor() ->getMock(); - $customerEntity->expects($this->any())->method('filterEntityCollection')->willReturnArgument(0); - $customerEntity->expects($this->any())->method('setParameters')->willReturnSelf(); + $customerEntity->method('filterEntityCollection')->willReturnArgument(0); + $customerEntity->method('setParameters')->willReturnSelf(); $data = [ 'translator' => $translator, 'attribute_collection' => $attributeCollection, - 'page_size' => 1, - 'collection_by_pages_iterator' => $byPagesIterator, + 'page_size' => $pageSize, 'entity_type_id' => 1, 'customer_collection' => $customerCollection, 'customer_entity' => $customerEntity, @@ -228,36 +233,6 @@ public function getWebsites($withDefault = false) return $websites; } - /** - * Iterate stub - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * - * @param AbstractDb $collection - * @param int $pageSize - * @param array $callbacks - */ - public function iterate(AbstractDb $collection, $pageSize, array $callbacks) - { - $resource = $this->createPartialMock(Customer::class, ['getIdFieldName']); - $resource->expects($this->any())->method('getIdFieldName')->willReturn('id'); - $arguments = [ - 'data' => $this->_customerData, - 'resource' => $resource, - $this->createMock(Share::class), - $this->createMock(AddressFactory::class), - $this->createMock(\Magento\Customer\Model\ResourceModel\Address\CollectionFactory::class), - $this->createMock(GroupFactory::class), - $this->createMock(\Magento\Customer\Model\AttributeFactory::class), - ]; - /** @var $customer \Magento\Customer\Model\Customer|MockObject */ - $customer = $this->_objectManager->getObject(\Magento\Customer\Model\Customer::class, $arguments); - - foreach ($callbacks as $callback) { - call_user_func($callback, $customer); - } - } - /** * Test for method exportItem() * diff --git a/app/code/Magento/Indexer/Model/ProcessManager.php b/app/code/Magento/Indexer/Model/ProcessManager.php index 2b25c8c6a3d15..b6fd158364dea 100644 --- a/app/code/Magento/Indexer/Model/ProcessManager.php +++ b/app/code/Magento/Indexer/Model/ProcessManager.php @@ -111,9 +111,12 @@ private function multiThreadsExecute($userFunctions) $this->startChildProcess($userFunction); } } - // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock,Magento2.Functions.DiscouragedFunction + // phpcs:ignore Magento2.Functions.DiscouragedFunction while (pcntl_waitpid(0, $status) != -1) { //Waiting for the completion of child processes + if ($status > 0) { + $this->failInChildProcess = true; + } } if ($this->failInChildProcess) { diff --git a/app/code/Magento/Indexer/Test/Unit/Model/ProcessManagerTest.php b/app/code/Magento/Indexer/Test/Unit/Model/ProcessManagerTest.php new file mode 100644 index 0000000000000..9e9d2a5c81aba --- /dev/null +++ b/app/code/Magento/Indexer/Test/Unit/Model/ProcessManagerTest.php @@ -0,0 +1,183 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Indexer\Test\Unit\Model; + +use Magento\Framework\App\ResourceConnection; +use Magento\Indexer\Model\ProcessManager; +use PHPUnit\Framework\TestCase; + +/** + * Class covers process manager execution test logic + */ +class ProcessManagerTest extends TestCase +{ + /** + * @dataProvider functionsWithErrorProvider + * @param array $userFunctions + * @param int $threadsCount + * @return void + */ + public function testFailureInChildProcessHandleMultiThread(array $userFunctions, int $threadsCount): void + { + $connectionMock = $this->createMock(ResourceConnection::class); + $processManager = new ProcessManager( + $connectionMock, + null, + $threadsCount + ); + + try { + $processManager->execute($userFunctions); + $this->fail('Exception was not handled'); + } catch (\RuntimeException $exception) { + $this->assertEquals('Fail in child process', $exception->getMessage()); + } + } + + /** + * Closure functions data provider for multi thread execution + * + * @return array + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function functionsWithErrorProvider(): array + { + return [ + 'more_threads_than_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(1); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 4, + ], + 'less_threads_than_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(1); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 2, + ], + 'equal_threads_and_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(1); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 3, + ], + ]; + } + + /** + * @dataProvider successFunctionsProvider + * @param array $userFunctions + * @param int $threadsCount + * @return void + */ + public function testSuccessChildProcessHandleMultiThread(array $userFunctions, int $threadsCount): void + { + $connectionMock = $this->createMock(ResourceConnection::class); + $processManager = new ProcessManager( + $connectionMock, + null, + $threadsCount + ); + + try { + $processManager->execute($userFunctions); + } catch (\RuntimeException $exception) { + $this->fail('Exception was not handled'); + } + } + + /** + * Closure functions data provider for multi thread execution + * + * @return array + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function successFunctionsProvider(): array + { + return [ + 'more_threads_than_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(0); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 4, + ], + 'less_threads_than_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(0); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 2, + ], + 'equal_threads_and_functions' => [ + 'user_functions' => [ + // @codingStandardsIgnoreStart + function () { + exit(0); + }, + function () { + exit(0); + }, + function () { + exit(0); + }, + // @codingStandardsIgnoreEnd + ], + 'threads_count' => 3, + ], + ]; + } +} diff --git a/app/code/Magento/Paypal/Controller/Hostedpro/ReturnAction.php b/app/code/Magento/Paypal/Controller/Hostedpro/ReturnAction.php index bb8b5f8fa0b46..dbaf432878de9 100644 --- a/app/code/Magento/Paypal/Controller/Hostedpro/ReturnAction.php +++ b/app/code/Magento/Paypal/Controller/Hostedpro/ReturnAction.php @@ -26,11 +26,7 @@ class ReturnAction extends Action implements CsrfAwareActionInterface, HttpPostA */ public function execute() { - $session = $this->_objectManager->get(\Magento\Checkout\Model\Session::class); - //TODO: some actions with order - if ($session->getLastRealOrderId()) { - $this->_redirect('checkout/onepage/success'); - } + $this->_redirect('checkout/onepage/success'); } /** diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Gateway.php b/app/code/Magento/Paypal/Model/Payflow/Service/Gateway.php index 6a2229c3d55ca..374af021cbf38 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Service/Gateway.php +++ b/app/code/Magento/Paypal/Model/Payflow/Service/Gateway.php @@ -85,7 +85,8 @@ public function postRequest(DataObject $request, ConfigInterface $config) ); $client->setConfig($clientConfig); $client->setMethod(\Zend_Http_Client::POST); - $client->setParameterPost($request->getData()); + $requestData = $this->prepareRequestData($request->getData()); + $client->setParameterPost($requestData); $client->setHeaders( [ 'X-VPS-VIT-CLIENT-CERTIFICATION-ID' => '33baf5893fc2123d8b191d2d011b7fdc', @@ -97,9 +98,7 @@ public function postRequest(DataObject $request, ConfigInterface $config) try { $response = $client->request(); - - $responseArray = []; - parse_str(strstr($response->getBody(), 'RESULT'), $responseArray); + $responseArray = $this->parseNVP(strstr($response->getBody(), 'RESULT')); $result->setData(array_change_key_case($responseArray, CASE_LOWER)); $result->setData('result_code', $result->getData('result')); @@ -115,7 +114,7 @@ public function postRequest(DataObject $request, ConfigInterface $config) } finally { $this->logger->debug( [ - 'request' => $request->getData(), + 'request' => $requestData, 'result' => $result->getData() ], (array)$config->getValue('getDebugReplacePrivateDataKeys'), @@ -125,4 +124,63 @@ public function postRequest(DataObject $request, ConfigInterface $config) return $result; } + + /** + * Add length tag to parameters name which contains special characters: =, & + * + * The length tag specifies the exact number of characters and spaces (number of bytes) that appear in the value + * eg ['COMPANYNAME[14]' => 'Ruff & Johnson')] + * + * @param array $data + * @return array + */ + private function prepareRequestData(array $data): array + { + $requestData = []; + foreach ($data as $k => $v) { + if (strpos($v, '&') !== false || strpos($v, '=') !== false) { + $requestData[$k . '[' . strlen($v) . ']'] = $v; + } else { + $requestData[$k] = $v; + } + } + return $requestData; + } + + /** + * Parse NVP string into array + * + * Use length tag (if present) to parse the key value. + * + * The length tag specifies the exact number of characters and spaces (number of bytes) that appear in the value + * e.g COMPANYNAME[14]=Ruff & Johnson + * e.g COMMENT1[7]=Level=5 + * + * @param string $nvp + * @return array + */ + private function parseNVP(string $nvp): array + { + $result = []; + while (strlen($nvp) > 0) { + $keyPos = strpos($nvp, '='); + if ($keyPos !== false) { + $key = substr($nvp, 0, $keyPos); + if (preg_match('/\[(\d+)]$/', $key, $keyParts)) { + $valueLength = (int) $keyParts[1]; + $key = substr($key, 0, strpos($key, '[')); + $result[$key] = substr($nvp, $keyPos + 1, $valueLength); + $valuePos = $keyPos + 1 + $valueLength; + } else { + $valuePos = strpos($nvp, '&') ? strpos($nvp, '&') : strlen($nvp); + $value = substr($nvp, $keyPos + 1, $valuePos - $keyPos - 1); + $result[$key] = $value; + } + $nvp = substr($nvp, $valuePos + 1); + } else { + $nvp = ''; + } + } + return $result; + } } diff --git a/app/code/Magento/Paypal/Plugin/TransparentSessionChecker.php b/app/code/Magento/Paypal/Plugin/TransparentSessionChecker.php index 5157ba3208fb7..d53fd183c1942 100644 --- a/app/code/Magento/Paypal/Plugin/TransparentSessionChecker.php +++ b/app/code/Magento/Paypal/Plugin/TransparentSessionChecker.php @@ -15,7 +15,13 @@ */ class TransparentSessionChecker { - private const TRANSPARENT_REDIRECT_PATH = 'paypal/transparent/redirect'; + /** + * @var string[] + */ + private $disableSessionUrls = [ + 'paypal/transparent/redirect', + 'paypal/hostedpro/return', + ]; /** * @var Http @@ -45,6 +51,12 @@ public function afterCheck(SessionStartChecker $subject, bool $result): bool return false; } - return strpos((string)$this->request->getPathInfo(), self::TRANSPARENT_REDIRECT_PATH) === false; + foreach ($this->disableSessionUrls as $url) { + if (strpos((string)$this->request->getPathInfo(), $url) !== false) { + return false; + } + } + + return true; } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/GatewayTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/GatewayTest.php index 194b708a0352b..a2d8111ec33c6 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/GatewayTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/GatewayTest.php @@ -17,27 +17,43 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use ReflectionMethod; +use Zend_Http_Client_Exception; +use Zend_Http_Response; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class GatewayTest extends TestCase { - /** @var Gateway|MockObject */ - protected $object; - - /** @var ZendClientFactory|MockObject */ - protected $httpClientFactoryMock; - - /** @var Random|MockObject */ - protected $mathRandomMock; - - /** @var Logger|MockObject */ - protected $loggerMock; - - /** @var ZendClient|MockObject */ - protected $zendClientMock; - + /** + * @var Gateway|MockObject + */ + private $object; + + /** + * @var ZendClientFactory|MockObject + */ + private $httpClientFactoryMock; + + /** + * @var Random|MockObject + */ + private $mathRandomMock; + + /** + * @var Logger|MockObject + */ + private $loggerMock; + + /** + * @var ZendClient|MockObject + */ + private $zendClientMock; + + /** + * @inheritdoc + */ protected function setUp(): void { $this->httpClientFactoryMock = $this->getMockBuilder(ZendClientFactory::class) @@ -66,24 +82,28 @@ protected function setUp(): void ); } - public function testPostRequestOk() + /** + * @param string $nvpResponse + * @param array $expectedResult + * @dataProvider postRequestOkDataProvider + */ + public function testPostRequestOk(string $nvpResponse, array $expectedResult): void { $configMap = [ ['getDebugReplacePrivateDataKeys', null, ['masked']], ['debug', null, true] ]; - $expectedResponse = 'RESULT=0&RESPMSG=Approved&SECURETOKEN=8ZIaw2&SECURETOKENID=2481d53'; /** @var ConfigInterface|MockObject $configInterfaceMock */ $configInterfaceMock = $this->getMockBuilder(ConfigInterface::class) ->getMockForAbstractClass(); - $zendResponseMock = $this->getMockBuilder(\Zend_Http_Response::class) + $zendResponseMock = $this->getMockBuilder(Zend_Http_Response::class) ->setMethods(['getBody']) ->disableOriginalConstructor() ->getMock(); $zendResponseMock->expects(static::once()) ->method('getBody') - ->willReturn($expectedResponse); + ->willReturn($nvpResponse); $this->zendClientMock->expects(static::once()) ->method('request') ->willReturn($zendResponseMock); @@ -98,8 +118,119 @@ public function testPostRequestOk() $result = $this->object->postRequest($object, $configInterfaceMock); - static::assertInstanceOf(DataObject::class, $result); - static::assertArrayHasKey('result_code', $result->getData()); + static::assertEquals($expectedResult, $result->toArray()); + } + + /** + * @return array[] + */ + public function postRequestOkDataProvider(): array + { + return [ + [ + 'RESULT=0&RESPMSG=Approved&SECURETOKEN=9tl4MmP46NUadl9pwCKFgfQjA' + . '&SECURETOKENID=vVWBMSNb9j0SLlYw4AbqBnKmuogtzNNC', + [ + 'result' => '0', + 'securetoken' => '9tl4MmP46NUadl9pwCKFgfQjA', + 'securetokenid' => 'vVWBMSNb9j0SLlYw4AbqBnKmuogtzNNC', + 'respmsg' => 'Approved', + 'result_code' => '0', + ] + ], + [ + 'RESULT=0&PNREF=A30A3A958244&RESPMSG=Approved&AUTHCODE=028PNI&AVSADDR=N&AVSZIP=N&HOSTCODE=A' + . '&PROCAVS=N&VISACARDLEVEL=12&TRANSTIME=2020-12-16 14:43:57&FIRSTNAME[4]=Joé' + . '&LASTNAME=O\'Reilly&COMPANYNAME[14]=Ruff & Johnson&COMMENT1[7]=Level=5' + . '&AMT=30.00&ACCT=1111&EXPDATE=1224&CARDTYPE=0&IAVS=N', + [ + 'result' => '0', + 'pnref' => 'A30A3A958244', + 'respmsg' => 'Approved', + 'authcode' => '028PNI', + 'avsaddr' => 'N', + 'avszip' => 'N', + 'hostcode' => 'A', + 'procavs' => 'N', + 'visacardlevel' => '12', + 'transtime' => '2020-12-16 14:43:57', + 'firstname' => 'Joé', + 'lastname' => 'O\'Reilly', + 'companyname' => 'Ruff & Johnson', + 'comment1' => 'Level=5', + 'amt' => '30.00', + 'acct' => '1111', + 'expdate' => '1224', + 'cardtype' => '0', + 'iavs' => 'N', + 'result_code' => '0', + ] + ], + ]; + } + + /** + * @param array $requestData + * @param string $requestBody + * @dataProvider requestBodyDataProvider + */ + public function testRequestBody(array $requestData, string $requestBody): void + { + $configMap = [ + ['getDebugReplacePrivateDataKeys', null, ['masked']], + ['debug', null, true] + ]; + + /** @var ConfigInterface|MockObject $configInterfaceMock */ + $configInterfaceMock = $this->getMockBuilder(ConfigInterface::class) + ->getMockForAbstractClass(); + $zendResponseMock = $this->getMockBuilder(Zend_Http_Response::class) + ->setMethods(['getBody']) + ->disableOriginalConstructor() + ->getMock(); + $zendResponseMock->expects(static::once()) + ->method('getBody') + ->willReturn('RESULT=0&RESPMSG=Approved'); + $this->zendClientMock->expects(static::once()) + ->method('request') + ->willReturn($zendResponseMock); + + $configInterfaceMock->expects(static::any()) + ->method('getValue') + ->willReturnMap($configMap); + $this->loggerMock->expects(static::once()) + ->method('debug'); + + $request = new DataObject($requestData); + $this->object->postRequest($request, $configInterfaceMock); + $method = new ReflectionMethod($this->zendClientMock, '_prepareBody'); + $method->setAccessible(true); + $this->assertEquals($requestBody, $method->invoke($this->zendClientMock)); + } + + /** + * @return array[] + */ + public function requestBodyDataProvider(): array + { + return [ + [ + [ + 'companyname' => 'Ruff & Johnson', + 'comment1' => 'Level=5', + 'shiptofirstname' => 'Joé', + 'shiptolastname' => 'O\'Reilly', + 'shiptostreet' => '4659 Rainbow Road', + 'shiptocity' => 'Los Angeles', + 'shiptostate' => 'CA', + 'shiptozip' => '90017', + 'shiptocountry' => 'US', + ], + 'companyname[14]=Ruff & Johnson&comment1[7]=Level=5&shiptofirstname=Joé&shiptolastname=O\'Reilly' + . '&shiptostreet=4659 Rainbow Road&shiptocity=Los Angeles&shiptostate=CA&shiptozip=90017' + . '&shiptocountry=US' + ] + ]; } public function testPostRequestFail() @@ -108,7 +239,7 @@ public function testPostRequestFail() /** @var ConfigInterface|MockObject $configInterfaceMock */ $configInterfaceMock = $this->getMockBuilder(ConfigInterface::class) ->getMockForAbstractClass(); - $zendResponseMock = $this->getMockBuilder(\Zend_Http_Response::class) + $zendResponseMock = $this->getMockBuilder(Zend_Http_Response::class) ->setMethods(['getBody']) ->disableOriginalConstructor() ->getMock(); @@ -116,7 +247,7 @@ public function testPostRequestFail() ->method('getBody'); $this->zendClientMock->expects(static::once()) ->method('request') - ->willThrowException(new \Zend_Http_Client_Exception()); + ->willThrowException(new Zend_Http_Client_Exception()); $object = new DataObject(); $this->object->postRequest($object, $configInterfaceMock); diff --git a/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGoToOrdersReportPageActionGroup.xml b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGoToOrdersReportPageActionGroup.xml new file mode 100644 index 0000000000000..b8f117a0de4bc --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/ActionGroup/AdminGoToOrdersReportPageActionGroup.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="AdminGoToOrdersReportPageActionGroup"> + <annotations> + <description>Redirects to the Orders Report page</description> + </annotations> + + <amOnPage url="{{OrdersReportPage.url}}" stepKey="goToOrdersReportPage"/> + <waitForPageLoad stepKey="waitForOrdersReportPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/AdminCanceledOrdersInOrderSalesReportTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/AdminCanceledOrdersInOrderSalesReportTest.xml new file mode 100644 index 0000000000000..e56d2b5bcbe6e --- /dev/null +++ b/app/code/Magento/Reports/Test/Mftf/Test/AdminCanceledOrdersInOrderSalesReportTest.xml @@ -0,0 +1,101 @@ +<?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="AdminCanceledOrdersInOrderSalesReportTest"> + <annotations> + <features value="Reports"/> + <stories value="Order Sales Report includes canceled orders"/> + <group value="reports"/> + <title value="Canceled orders in order sales report"/> + <description value="Verify canceling of orders in order sales report"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-95960"/> + <useCaseId value="MAGETWO-95823"/> + </annotations> + + <before> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <createData entity="CustomerCart" stepKey="createCustomerCartOne"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addCartItemOne"> + <requiredEntity createDataKey="createCustomerCartOne"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddress"> + <requiredEntity createDataKey="createCustomerCartOne"/> + </createData> + <updateData createDataKey="createCustomerCartOne" entity="CustomerOrderPaymentMethod" stepKey="sendCustomerPaymentInformationOne"> + <requiredEntity createDataKey="createCustomerCartOne"/> + </updateData> + <createData entity="Invoice" stepKey="invoiceOrderOne"> + <requiredEntity createDataKey="createCustomerCartOne"/> + </createData> + <createData entity="Shipment" stepKey="shipOrderOne"> + <requiredEntity createDataKey="createCustomerCartOne"/> + </createData> + + <createData entity="CustomerCart" stepKey="createCustomerCartTwo"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addCartItemTwo"> + <requiredEntity createDataKey="createCustomerCartTwo"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddressTwo"> + <requiredEntity createDataKey="createCustomerCartTwo"/> + </createData> + <updateData createDataKey="createCustomerCartTwo" entity="CustomerOrderPaymentMethod" stepKey="sendCustomerPaymentInformationTwo"> + <requiredEntity createDataKey="createCustomerCartTwo"/> + </updateData> + <createData entity="CancelOrder" stepKey="cancelOrderTwo"> + <requiredEntity createDataKey="createCustomerCartTwo"/> + </createData> + </before> + + <after> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <actionGroup ref="AdminGoToOrdersReportPageActionGroup" stepKey="goToOrdersReportPage1"/> + <generateDate stepKey="generateEndDate" date="+0 day" format="m/d/Y"/> + <generateDate stepKey="generateStartDate" date="-1 day" format="m/d/Y"/> + <actionGroup ref="GenerateOrderReportForNotCancelActionGroup" stepKey="generateReportAfterCancelOrderBefore"> + <argument name="orderFromDate" value="$generateStartDate"/> + <argument name="orderToDate" value="$generateEndDate"/> + <argument name="statuses" value="['closed', 'complete', 'fraud', 'holded', 'payment_review', 'paypal_canceled_reversal', 'paypal_reversed', 'processing']"/> + </actionGroup> + <waitForElement selector="{{GeneratedReportSection.ordersCount}}" stepKey="waitForOrdersCountBefore"/> + <grabTextFrom selector="{{GeneratedReportSection.ordersCount}}" stepKey="grabCanceledOrdersSpecified"/> + + <actionGroup ref="AdminGoToOrdersReportPageActionGroup" stepKey="goToOrdersReportPage2"/> + <actionGroup ref="GenerateOrderReportActionGroup" stepKey="generateReportAfterCancelOrder"> + <argument name="orderFromDate" value="$generateStartDate"/> + <argument name="orderToDate" value="$generateEndDate"/> + </actionGroup> + <waitForElement selector="{{GeneratedReportSection.ordersCount}}" stepKey="waitForOrdersCount"/> + <grabTextFrom selector="{{GeneratedReportSection.ordersCount}}" stepKey="grabCanceledOrdersAny"/> + + <assertEquals stepKey="assertEquals"> + <actualResult type="string">{$grabCanceledOrdersAny}</actualResult> + <expectedResult type="string">{$grabCanceledOrdersSpecified}</expectedResult> + </assertEquals> + </test> +</tests> diff --git a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml index 6e9e8e800e076..54d3059f24532 100644 --- a/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml +++ b/app/code/Magento/Reports/Test/Mftf/Test/CancelOrdersInOrderSalesReportTest.xml @@ -7,16 +7,19 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CancelOrdersInOrderSalesReportTest"> + <test name="CancelOrdersInOrderSalesReportTest" deprecated="Use AdminCanceledOrdersInOrderSalesReportTest instead"> <annotations> <features value="Reports"/> <stories value="Order Sales Report includes canceled orders"/> <group value="reports"/> - <title value="Canceled orders in order sales report"/> + <title value="DEPRECATED. Canceled orders in order sales report"/> <description value="Verify canceling of orders in order sales report"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-95960"/> <useCaseId value="MAGETWO-95823"/> + <skip> + <issueId value="DEPRECATED">Use AdminCanceledOrdersInOrderSalesReportTest instead</issueId> + </skip> </annotations> <before> diff --git a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml index 26d0e8b13659d..b9d4572cd4868 100644 --- a/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml +++ b/app/code/Magento/Reports/view/adminhtml/layout/reports_report_review_product_grid.xml @@ -90,8 +90,8 @@ <arguments> <argument name="header" xsi:type="string" translate="true">Last Review</argument> <argument name="type" xsi:type="string">datetime</argument> - <argument name="id" xsi:type="string">created_at</argument> - <argument name="index" xsi:type="string">created_at</argument> + <argument name="id" xsi:type="string">last_review</argument> + <argument name="index" xsi:type="string">last_review</argument> <argument name="column_css_class" xsi:type="string">col-date</argument> <argument name="header_css_class" xsi:type="string">col-date</argument> </arguments> diff --git a/app/code/Magento/Review/Block/View.php b/app/code/Magento/Review/Block/View.php index fcfa11faa169d..bbdd246835f9e 100644 --- a/app/code/Magento/Review/Block/View.php +++ b/app/code/Magento/Review/Block/View.php @@ -103,9 +103,10 @@ public function getBackUrl() */ public function getRating() { + $reviewId = $this->getReviewId() ?: $this->getReviewData()->getId(); if (!$this->getRatingCollection()) { $ratingCollection = $this->_voteFactory->create()->getResourceCollection()->setReviewFilter( - $this->getReviewId() + $reviewId )->setStoreFilter( $this->_storeManager->getStore()->getId() )->addRatingInfo( diff --git a/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFilterProductReviewByNameActionGroup.xml b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFilterProductReviewByNameActionGroup.xml new file mode 100644 index 0000000000000..b0544081980bb --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/ActionGroup/AdminFilterProductReviewByNameActionGroup.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="AdminFilterProductReviewByNameActionGroup"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <waitForPageLoad stepKey="waitForGridToAppear"/> + <fillField userInput="{{productName}}" selector="{{AdminCreateNewReviewSection.filterProductName}}" stepKey="searchReview"/> + <click selector="{{AdminCreateNewReviewSection.searchButton}}" stepKey="startSearch"/> + <waitForPageLoad stepKey="waitForResults"/> + <see userInput="{{productName}}" selector="{{AdminCreateNewReviewSection.gridProductColumn}}" stepKey="assertReviewColumn"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Review/Test/Mftf/Data/ProductReviewData.xml b/app/code/Magento/Review/Test/Mftf/Data/ProductReviewData.xml index f66decd1b7bd0..ba2102d0ee1f1 100644 --- a/app/code/Magento/Review/Test/Mftf/Data/ProductReviewData.xml +++ b/app/code/Magento/Review/Test/Mftf/Data/ProductReviewData.xml @@ -16,4 +16,20 @@ <item>Default Store View</item> </array> </entity> + <entity name="firstSimpleProductReview"> + <data key="nickname" unique="suffix">user1</data> + <data key="title">Review title 1</data> + <data key="detail">Simple product review 1</data> + <array key="select_stores"> + <item>Default Store View</item> + </array> + </entity> + <entity name="secondSimpleProductReview"> + <data key="nickname" unique="suffix">user2</data> + <data key="title">Review title 2</data> + <data key="detail">Simple product review 2</data> + <array key="select_stores"> + <item>Default Store View</item> + </array> + </entity> </entities> diff --git a/app/code/Magento/Review/Test/Mftf/Section/AdminCreateNewReviewSection.xml b/app/code/Magento/Review/Test/Mftf/Section/AdminCreateNewReviewSection.xml index 3b17b20e9da1b..28eb3112f259a 100644 --- a/app/code/Magento/Review/Test/Mftf/Section/AdminCreateNewReviewSection.xml +++ b/app/code/Magento/Review/Test/Mftf/Section/AdminCreateNewReviewSection.xml @@ -18,8 +18,13 @@ <element name="submitReview" type="button" selector="#save_button"/> <element name="SuccessMessage" type="button" selector="div.message-success"/> <element name="gridProducts_filter_review_cnt" type="button" selector="#gridProducts_filter_review_cnt"/> + <element name="filterProductName" type="button" selector="#gridProducts_filter_name"/> <element name="searchButton" type="button" selector="//*[@id='gridProducts']//button[contains(@title, 'Search')]"/> <element name="gridReviewColumn" type="text" selector="//tbody//td[@data-column='review_cnt']"/> + <element name="gridLastReviewColumn" type="text" selector="//tbody//td[@data-column='created_at']"/> + <element name="gridProductColumn" type="text" selector="//tbody//td[@data-column='name']"/> + <element name="showReviewsButton" type="text" selector="//tbody//td[@data-column='action']"/> + <element name="grabLatestUserReviewDate" type="text" selector="//table[@class='data-grid']//tbody//tr[position()=1]//td[position()=3]"/> <element name="gridCustomer_filter_review_cnt" type="button" selector="#customers_grid_filter_review_cnt"/> <element name="CustomerSearchButton" type="button" selector="//*[@id='customers_grid']//button[contains(@title, 'Search')]"/> </section> diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml new file mode 100644 index 0000000000000..3405314f24f78 --- /dev/null +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml @@ -0,0 +1,83 @@ +<?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="AdminValidateLastReviewDateForReviewsByProductsReportTest"> + <annotations> + <features value="Review"/> + <stories value="Reports: Review by Products"/> + <title value="Admin Validate Last Review Date For Review by Products Reports"/> + <description value="Admin Validate Last Review Date For Review by Products Reports"/> + <severity value="MAJOR"/> + <useCaseId value="MC-39737"/> + <testCaseId value="MC-39838"/> + </annotations> + <before> + <!--Step1. Login as admin--> + <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> + <!--Step2. Create product and Category--> + <createData stepKey="category" entity="SimpleSubCategory"/> + <createData stepKey="createProduct" entity="SimpleProduct"> + <requiredEntity createDataKey="category"/> + </createData> + </before> + <after> + <!--Step9. Delete newly created product reviews --> + <actionGroup ref="AdminOpenReviewsPageActionGroup" stepKey="openAllReviewsPage"/> + <actionGroup ref="AdminDeleteReviewsByUserNicknameActionGroup" stepKey="deleteFirstCustomerReview"> + <argument name="nickname" value="{{firstSimpleProductReview.nickname}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteReviewsByUserNicknameActionGroup" stepKey="deleteSecondCustomerReview"> + <argument name="nickname" value="{{secondSimpleProductReview.nickname}}"/> + </actionGroup> + <!--Step10. delete Category and Products --> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <!--Step11. Admin Logout--> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + <!--Step3. Navigate to Marketing > User Content> All Review --> + <amOnPage url="{{AdminReviewsPage.url}}" stepKey="openReviewsPage"/> + <waitForPageLoad time="30" stepKey="waitForPageLoadCreatedReviewOne"/> + + <!--Step4. Add First and Second Review For Same Product--> + <actionGroup ref="AdminAddProductReviewActionGroup" stepKey="addFirstReview"> + <argument name="review" value="firstSimpleProductReview"/> + <argument name="sku" value="$$createProduct.sku$$"/> + </actionGroup> + <amOnPage url="{{AdminReviewsPage.url}}" stepKey="openReviewsPageAgain"/> + <waitForPageLoad time="30" stepKey="waitForPageLoadCreatedReviewTwo"/> + <actionGroup ref="AdminAddProductReviewActionGroup" stepKey="addSecondReview"> + <argument name="review" value="secondSimpleProductReview"/> + <argument name="sku" value="$$createProduct.sku$$"/> + </actionGroup> + <!--Step5. Navigate to Reports > Reviews > By Products --> + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="navigateToReportsByProductsPage"> + <argument name="menuUiId" value="{{AdminMenuReports.dataUiId}}"/> + <argument name="submenuUiId" value="{{AdminMenuReportsReviewsByProducts.dataUiId}}"/> + </actionGroup> + <!--Step6. Search product review by product name --> + <actionGroup ref="AdminFilterProductReviewByNameActionGroup" stepKey="navigateToReportsReview"> + <argument name="productName" value="$$createProduct.name$$"/> + </actionGroup> + <!--Step7. Click 'Show Reviews' to see review details--> + <grabTextFrom selector="{{AdminCreateNewReviewSection.gridLastReviewColumn}}" stepKey="grabLastReviewDate"/> + <click selector="{{AdminCreateNewReviewSection.showReviewsButton}}" stepKey="showReviewsPage"/> + <waitForPageLoad stepKey="waitForReviewListPageToLoad"/> + <!--Step8. Assert product last review date matches latest user review date--> + <fillField selector="{{AdminReviewGridSection.nickname}}" userInput="{{secondSimpleProductReview.nickname}}" stepKey="fillNickname"/> + <click selector="{{AdminDataGridHeaderSection.applyFilters}}" stepKey="clickApplyFilters"/> + <waitForPageLoad stepKey="waitForGridViewPageToLoad"/> + <grabTextFrom selector="{{AdminCreateNewReviewSection.grabLatestUserReviewDate}}" stepKey="grabLatestUserReviewDate"/> + <assertEquals stepKey="assertReviewDate"> + <actualResult type="string">$grabLastReviewDate</actualResult> + <expectedResult type="string">$grabLatestUserReviewDate</expectedResult> + </assertEquals> + </test> +</tests> diff --git a/app/code/Magento/Review/view/frontend/templates/view.phtml b/app/code/Magento/Review/view/frontend/templates/view.phtml index b51353b7df685..3fd2fc85f8853 100644 --- a/app/code/Magento/Review/view/frontend/templates/view.phtml +++ b/app/code/Magento/Review/view/frontend/templates/view.phtml @@ -33,16 +33,26 @@ <caption class="table-caption"><?= $block->escapeHtml(__('Product Rating')) ?></caption> <?php foreach ($block->getRating() as $_rating): ?> <?php if ($_rating->getPercent()): ?> + <?php $rating = ceil($_rating->getPercent()) ?> <tr> - <td class="label"><?= $block->escapeHtml(__($_rating->getRatingCode())) ?></td> + <td class="label" width="10%"> + <?= $block->escapeHtml(__($_rating->getRatingCode())) ?> + </td> <td class="value"> - <div class="rating-box"> - <div class="rating"/> + <?php $ratingId = $_rating->getRatingId() ?> + <div class="rating-summary item" + id="rating-div-<?= $block->escapeHtml($ratingId) ?>"> + <div class="rating-result" title="<?= /* @noEscape */ $rating ?>%"> + <span> + <span><?= /* @noEscape */ $rating ?>%</span> + </span> + </div> + <?= /* @noEscape */ $secureRenderer->renderStyleAsTag( + "width:" . /* @noEscape */ $rating . "%", + 'div#rating-div-'.$_rating->getRatingId(). + '>div.rating-result>span:first-child' + ) ?> </div> - <?= /* @noEscape */ $secureRenderer->renderStyleAsTag( - "width:" . /* @noEscape */ ceil($_rating->getPercent()) . "%;", - 'div.rating-box div.rating' - ) ?> </td> </tr> <?php endif; ?> diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php index 67fc3590ac501..d5d3b80755360 100644 --- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php +++ b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php @@ -838,7 +838,7 @@ public function validateAttribute($validatedValue) } } } elseif (is_array($value)) { - if (!is_array($validatedValue)) { + if (!is_array($validatedValue) || empty($validatedValue)) { return false; } $result = array_intersect($value, $validatedValue); diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php index 3c55eacaff559..91f1c4b942f75 100644 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php +++ b/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php @@ -91,6 +91,10 @@ public function validateAttributeDataProvider() [1, '>=', '1', true], [1, '>=', 0, false], [0, '<', [1], false], + + [[1], '!{}', [], false], + [[1], '!{}', [1], false], + [[1], '!{}', [0], false], ]; } @@ -176,6 +180,8 @@ public function validateAttributeArrayInputTypeDataProvider() [[3], '{}', [], false, 'grid'], [1, '{}', 1, false, 'grid'], [1, '!{}', [1, 2, 3], false, 'grid'], + [1, '!{}', [], false, 'grid'], + [[1], '!{}', [], false, 'grid'], [[1], '{}', null, false, 'grid'], [null, '{}', null, true, 'input'], [null, '!{}', null, false, 'input'], diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php index 5633e16d7d3d0..879baa948e919 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php @@ -27,6 +27,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Customer\Model\AttributeMetadataDataProvider; /** * Sales address save @@ -52,6 +53,11 @@ class AddressSave extends Order implements HttpPostActionInterface */ private $orderAddressRepository; + /** + * @var AttributeMetadataDataProvider + */ + private $attributeMetadataDataProvider; + /** * @param Context $context * @param Registry $coreRegistry @@ -82,7 +88,8 @@ public function __construct( OrderRepositoryInterface $orderRepository, LoggerInterface $logger, RegionFactory $regionFactory = null, - OrderAddressRepositoryInterface $orderAddressRepository = null + OrderAddressRepositoryInterface $orderAddressRepository = null, + AttributeMetadataDataProvider $attributeMetadataDataProvider = null ) { $this->regionFactory = $regionFactory ?: ObjectManager::getInstance()->get(RegionFactory::class); $this->orderAddressRepository = $orderAddressRepository ?: ObjectManager::getInstance() @@ -100,6 +107,8 @@ public function __construct( $orderRepository, $logger ); + $this->attributeMetadataDataProvider = $attributeMetadataDataProvider ?: ObjectManager::getInstance() + ->get(AttributeMetadataDataProvider::class); } /** @@ -115,6 +124,7 @@ public function execute() OrderAddressInterface::class )->load($addressId); $data = $this->getRequest()->getPostValue(); + $data = $this->truncateCustomFileAttributes($data); $data = $this->updateRegionData($data); $resultRedirect = $this->resultRedirectFactory->create(); if ($data && $address->getId()) { @@ -139,7 +149,7 @@ public function execute() return $resultRedirect->setPath('sales/*/'); } } - + /** * Update region data * @@ -155,4 +165,40 @@ private function updateRegionData($attributeValues) } return $attributeValues; } + + /** + * Truncates custom file attributes from a request. + * + * As custom file type attributes are not working workaround is introduced. + * + * @param array $data + * @return array + */ + private function truncateCustomFileAttributes(array $data): array + { + $foundArrays = []; + + foreach ($data as $value) { + if (is_array($value)) { + $foundArrays = $value; + } + } + + if (empty($foundArrays)) { + return $data; + } + + $attributesList = $this->attributeMetadataDataProvider->loadAttributesCollection( + 'customer_address', + 'adminhtml_customer_address' + ); + $attributesList->addFieldToFilter('is_user_defined', 1); + $attributesList->addFieldToFilter('frontend_input', 'file'); + + foreach ($attributesList as $customFileAttribute) { + unset($data[$customFileAttribute->getAttributeCode()]); + } + + return $data; + } } diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 5d621f1632837..6bd6e8e4e83e1 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -7,10 +7,12 @@ namespace Magento\Sales\Model\AdminOrder; use Magento\Customer\Api\AddressMetadataInterface; +use Magento\Customer\Api\Data\AttributeMetadataInterface; use Magento\Customer\Model\Metadata\Form as CustomerForm; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\App\ObjectManager; use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\Address\CustomAttributeListInterface; use Magento\Quote\Model\Quote\Item; use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Model\Order; @@ -250,6 +252,11 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\ */ private $storeManager; + /** + * @var CustomAttributeListInterface + */ + private $customAttributeList; + /** * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -282,6 +289,7 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\ * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer * @param ExtensibleDataObjectConverter|null $dataObjectConverter * @param StoreManagerInterface $storeManager + * @param CustomAttributeListInterface|null $customAttributeList * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -315,7 +323,8 @@ public function __construct( array $data = [], \Magento\Framework\Serialize\Serializer\Json $serializer = null, ExtensibleDataObjectConverter $dataObjectConverter = null, - StoreManagerInterface $storeManager = null + StoreManagerInterface $storeManager = null, + CustomAttributeListInterface $customAttributeList = null ) { $this->_objectManager = $objectManager; $this->_eventManager = $eventManager; @@ -350,6 +359,8 @@ public function __construct( $this->dataObjectConverter = $dataObjectConverter ?: ObjectManager::getInstance() ->get(ExtensibleDataObjectConverter::class); $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); + $this->customAttributeList = $customAttributeList ?: ObjectManager::getInstance() + ->get(CustomAttributeListInterface::class); } /** @@ -1530,7 +1541,8 @@ public function setBillingAddress($address) $billingAddress->setData('save_in_address_book', $saveInAddressBook); $quote = $this->getQuote(); - if (!$quote->isVirtual() && $this->getShippingAddress()->getSameAsBilling()) { + $shippingAddress = $this->getShippingAddress(); + if (!$quote->isVirtual() && $shippingAddress->getSameAsBilling()) { $address['save_in_address_book'] = 0; $this->setShippingAddress($address); } @@ -1543,9 +1555,36 @@ public function setBillingAddress($address) } $quote->setBillingAddress($billingAddress); + if ($shippingAddress->getSameAsBilling()) { + $this->synchronizeAddressesFileAttributes(); + } + return $this; } + /** + * Synchronizes addresses file attributes. + * + * @return void + */ + private function synchronizeAddressesFileAttributes(): void + { + $billingAddress = $this->getBillingAddress(); + $shippingAddress = $this->getShippingAddress(); + + /** @var AttributeMetadataInterface[] $customAttributes */ + $customAttributes = $this->customAttributeList->getAttributes(); + foreach ($customAttributes as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + if ($attribute->getFrontendInput() === 'file' + && !empty($billingAddress->getData($attributeCode)) + && empty($shippingAddress->getData($attributeCode)) + ) { + $shippingAddress->setData($attributeCode, $billingAddress->getData($attributeCode)); + } + } + } + /** * Set shipping method * diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php index 95dace13d832f..faed11c4f718e 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php @@ -5,22 +5,38 @@ */ namespace Magento\Sales\Model\Order\Creditmemo\Total; +use Magento\Sales\Api\Data\CreditmemoInterface; +use Magento\Sales\Model\Order\Creditmemo; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\ResourceModel\Order\Invoice as ResourceInvoice; + /** * Collects credit memo taxes. */ class Tax extends AbstractTotal { /** - * Collects credit memo taxes. - * - * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo - * @return $this - * + * @var ResourceInvoice + */ + private $resourceInvoice; + + /** + * @param ResourceInvoice $resourceInvoice + * @param array $data + */ + public function __construct(ResourceInvoice $resourceInvoice, array $data = []) + { + $this->resourceInvoice = $resourceInvoice; + parent::__construct($data); + } + + /** + * {@inheritdoc} * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) + public function collect(Creditmemo $creditmemo) { $shippingTaxAmount = 0; $baseShippingTaxAmount = 0; @@ -28,38 +44,37 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) $baseTotalTax = 0; $totalDiscountTaxCompensation = 0; $baseTotalDiscountTaxCompensation = 0; - $order = $creditmemo->getOrder(); - /** @var $item \Magento\Sales\Model\Order\Creditmemo\Item */ foreach ($creditmemo->getAllItems() as $item) { $orderItem = $item->getOrderItem(); if ($orderItem->isDummy() || $item->getQty() <= 0) { continue; } + $orderItemTax = (double)$orderItem->getTaxInvoiced(); $baseOrderItemTax = (double)$orderItem->getBaseTaxInvoiced(); $orderItemQty = (double)$orderItem->getQtyInvoiced(); if ($orderItemQty) { - /** - * Check item tax amount - */ - + /** Check item tax amount */ $tax = $orderItemTax - $orderItem->getTaxRefunded(); $baseTax = $baseOrderItemTax - $orderItem->getBaseTaxRefunded(); - $discountTaxCompensation = $orderItem->getDiscountTaxCompensationInvoiced() - - $orderItem->getDiscountTaxCompensationRefunded(); - $baseDiscountTaxCompensation = $orderItem->getBaseDiscountTaxCompensationInvoiced() - - $orderItem->getBaseDiscountTaxCompensationRefunded(); + $discountTaxCompensation = $orderItem->getDiscountTaxCompensationInvoiced() + - $orderItem->getDiscountTaxCompensationRefunded(); + $baseDiscountTaxCompensation = $orderItem->getBaseDiscountTaxCompensationInvoiced() + - $orderItem->getBaseDiscountTaxCompensationRefunded(); if (!$item->isLast()) { $availableQty = $orderItemQty - $orderItem->getQtyRefunded(); $tax = $creditmemo->roundPrice($tax / $availableQty * $item->getQty()); - $baseTax = $creditmemo->roundPrice($baseTax / $availableQty * $item->getQty(), 'base'); - $discountTaxCompensation = - $creditmemo->roundPrice($discountTaxCompensation / $availableQty * $item->getQty()); - $baseDiscountTaxCompensation = - $creditmemo->roundPrice($baseDiscountTaxCompensation / $availableQty * $item->getQty(), 'base'); + $baseTax = $creditmemo->roundPrice(($baseTax / $availableQty * $item->getQty()), 'base'); + $discountTaxCompensation = $creditmemo->roundPrice( + $discountTaxCompensation / $availableQty * $item->getQty() + ); + $baseDiscountTaxCompensation = $creditmemo->roundPrice( + $baseDiscountTaxCompensation / $availableQty * $item->getQty(), + 'base' + ); } $item->setTaxAmount($tax); @@ -77,14 +92,14 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) $isPartialShippingRefunded = false; $baseOrderShippingAmount = (float)$order->getBaseShippingAmount(); if ($invoice = $creditmemo->getInvoice()) { - //recalculate tax amounts in case if refund shipping value was changed + // recalculate tax amounts in case if refund shipping value was changed if ($baseOrderShippingAmount && $creditmemo->getBaseShippingAmount() !== null) { $taxFactor = $creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount; $shippingTaxAmount = $invoice->getShippingTaxAmount() * $taxFactor; $baseShippingTaxAmount = $invoice->getBaseShippingTaxAmount() * $taxFactor; $totalDiscountTaxCompensation += $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor; - $baseTotalDiscountTaxCompensation += - $invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor; + $baseTotalDiscountTaxCompensation += $invoice->getBaseShippingDiscountTaxCompensationAmnt() + * $taxFactor; $shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount); $baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base'); $totalDiscountTaxCompensation = $creditmemo->roundPrice($totalDiscountTaxCompensation); @@ -97,14 +112,11 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) } } else { $orderShippingAmount = $order->getShippingAmount(); - $baseOrderShippingRefundedAmount = $order->getBaseShippingRefunded(); - $shippingTaxAmount = 0; $baseShippingTaxAmount = 0; $shippingDiscountTaxCompensationAmount = 0; $baseShippingDiscountTaxCompensationAmount = 0; - $shippingDelta = $baseOrderShippingAmount - $baseOrderShippingRefundedAmount; if ($shippingDelta > $creditmemo->getBaseShippingAmount()) { @@ -113,45 +125,39 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) $shippingTaxAmount = $order->getShippingTaxAmount() * $part; $baseShippingTaxAmount = $order->getBaseShippingTaxAmount() * $basePart; $shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() * $part; - $baseShippingDiscountTaxCompensationAmount = - $order->getBaseShippingDiscountTaxCompensationAmnt() * $basePart; + $baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt() + * $basePart; $shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount); $baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base'); - $shippingDiscountTaxCompensationAmount = - $creditmemo->roundPrice($shippingDiscountTaxCompensationAmount); - $baseShippingDiscountTaxCompensationAmount = - $creditmemo->roundPrice($baseShippingDiscountTaxCompensationAmount, 'base'); + $shippingDiscountTaxCompensationAmount = $creditmemo->roundPrice( + $shippingDiscountTaxCompensationAmount + ); + $baseShippingDiscountTaxCompensationAmount = $creditmemo->roundPrice( + $baseShippingDiscountTaxCompensationAmount, + 'base' + ); if ($part < 1 && $order->getShippingTaxAmount() > 0) { $isPartialShippingRefunded = true; } } elseif ($shippingDelta == $creditmemo->getBaseShippingAmount()) { $shippingTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded(); $baseShippingTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded(); - $shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() - - $order->getShippingDiscountTaxCompensationRefunded(); - $baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt() - - $order->getBaseShippingDiscountTaxCompensationRefunded(); + $shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() + - $order->getShippingDiscountTaxCompensationRefunded(); + $baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt() + - $order->getBaseShippingDiscountTaxCompensationRefunded(); } + $totalTax += $shippingTaxAmount; $baseTotalTax += $baseShippingTaxAmount; $totalDiscountTaxCompensation += $shippingDiscountTaxCompensationAmount; $baseTotalDiscountTaxCompensation += $baseShippingDiscountTaxCompensationAmount; } - $allowedTax = $order->getTaxInvoiced() - $order->getTaxRefunded() - $creditmemo->getTaxAmount(); - $allowedBaseTax = $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded() - $creditmemo->getBaseTaxAmount(); - $allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationInvoiced() + - $order->getShippingDiscountTaxCompensationAmount() - - $order->getDiscountTaxCompensationRefunded() - - $order->getShippingDiscountTaxCompensationRefunded() - - $creditmemo->getDiscountTaxCompensationAmount() - - $creditmemo->getShippingDiscountTaxCompensationAmount(); - $allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationInvoiced() + - $order->getBaseShippingDiscountTaxCompensationAmnt() - - $order->getBaseDiscountTaxCompensationRefunded() - - $order->getBaseShippingDiscountTaxCompensationRefunded() - - $creditmemo->getBaseShippingDiscountTaxCompensationAmnt() - - $creditmemo->getBaseDiscountTaxCompensationAmount(); + $allowedTax = $this->calculateAllowedTax($creditmemo); + $allowedBaseTax = $this->calculateAllowedBaseTax($creditmemo); + $allowedDiscountTaxCompensation = $this->calculateAllowedDiscountTaxCompensation($creditmemo); + $allowedBaseDiscountTaxCompensation = $this->calculateAllowedBaseDiscountTaxCompensation($creditmemo); if ($creditmemo->isLast() && !$isPartialShippingRefunded) { $totalTax = $allowedTax; @@ -161,10 +167,11 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) } else { $totalTax = min($allowedTax, $totalTax); $baseTotalTax = min($allowedBaseTax, $baseTotalTax); - $totalDiscountTaxCompensation = - min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation); - $baseTotalDiscountTaxCompensation = - min($allowedBaseDiscountTaxCompensation, $baseTotalDiscountTaxCompensation); + $totalDiscountTaxCompensation = min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation); + $baseTotalDiscountTaxCompensation = min( + $allowedBaseDiscountTaxCompensation, + $baseTotalDiscountTaxCompensation + ); } $creditmemo->setTaxAmount($creditmemo->getTaxAmount() + $totalTax); @@ -177,9 +184,132 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) $creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $totalTax + $totalDiscountTaxCompensation); $creditmemo->setBaseGrandTotal( - $creditmemo->getBaseGrandTotal() + - $baseTotalTax + $baseTotalDiscountTaxCompensation + $creditmemo->getBaseGrandTotal() + $baseTotalTax + $baseTotalDiscountTaxCompensation ); return $this; + + } + + /** + * Calculate allowed to Credit Memo tax amount + * + * @param Creditmemo $creditMemo + * @return float + */ + private function calculateAllowedTax(Creditmemo $creditMemo): float + { + $invoice = $creditMemo->getInvoice(); + $order = $creditMemo->getOrder(); + if ($invoice!== null) { + $amount = $invoice->getTaxAmount() + - $this->calculateInvoiceRefundedAmount($invoice, CreditmemoInterface::TAX_AMOUNT); + } else { + $amount = $order->getTaxInvoiced() - $order->getTaxRefunded(); + } + + return (float) $amount - $creditMemo->getTaxAmount(); + } + + /** + * Calculate allowed to Credit Memo tax amount in the base currency + * + * @param Creditmemo $creditMemo + * @return float + */ + private function calculateAllowedBaseTax(Creditmemo $creditMemo): float + { + $invoice = $creditMemo->getInvoice(); + $order = $creditMemo->getOrder(); + + if ($invoice!== null) { + $amount = $invoice->getBaseTaxAmount() + - $this->calculateInvoiceRefundedAmount($invoice, CreditmemoInterface::BASE_TAX_AMOUNT); + } else { + $amount = $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded(); + } + + return (float) $amount - $creditMemo->getBaseTaxAmount(); + } + + /** + * Calculate allowed to Credit Memo discount tax compensation amount + * + * @param Creditmemo $creditMemo + * @return float + */ + private function calculateAllowedDiscountTaxCompensation(Creditmemo $creditMemo): float + { + $invoice = $creditMemo->getInvoice(); + $order = $creditMemo->getOrder(); + + if ($invoice) { + $amount = $invoice->getDiscountTaxCompensationAmount() + + $invoice->getShippingDiscountTaxCompensationAmount() + - $this->calculateInvoiceRefundedAmount( + $invoice, + CreditmemoInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT + ) - $this->calculateInvoiceRefundedAmount( + $invoice, + CreditmemoInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT + ); + } else { + $amount = $order->getDiscountTaxCompensationInvoiced() + + $order->getShippingDiscountTaxCompensationAmount() + - $order->getDiscountTaxCompensationRefunded() + - $order->getShippingDiscountTaxCompensationRefunded(); + } + + return (float) $amount + - $creditMemo->getDiscountTaxCompensationAmount() + - $creditMemo->getShippingDiscountTaxCompensationAmount(); + } + + /** + * Calculate allowed to Credit Memo discount tax compensation amount in the base currency + * + * @param Creditmemo $creditMemo + * @return float + */ + private function calculateAllowedBaseDiscountTaxCompensation(Creditmemo $creditMemo): float + { + $invoice = $creditMemo->getInvoice(); + $order = $creditMemo->getOrder(); + + if ($invoice) { + $amount = $invoice->getBaseDiscountTaxCompensationAmount() + + $invoice->getBaseShippingDiscountTaxCompensationAmnt() + - $this->calculateInvoiceRefundedAmount( + $invoice, + CreditmemoInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT + ) - $this->calculateInvoiceRefundedAmount( + $invoice, + CreditmemoInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT + ); + } else { + $amount = $order->getBaseDiscountTaxCompensationInvoiced() + + $order->getBaseShippingDiscountTaxCompensationAmnt() + - $order->getBaseDiscountTaxCompensationRefunded() + - $order->getBaseShippingDiscountTaxCompensationRefunded(); + } + + return (float) $amount + - $creditMemo->getBaseShippingDiscountTaxCompensationAmnt() + - $creditMemo->getBaseDiscountTaxCompensationAmount(); + } + + /** + * Calculate refunded amount for invoice + * + * @param Invoice $invoice + * @param string $field + * @return float + */ + private function calculateInvoiceRefundedAmount(Invoice $invoice, string $field): float + { + if (empty($invoice->getId())) { + return 0; + } + + return $this->resourceInvoice->calculateRefundedAmount((int)$invoice->getId(), $field); } } diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice.php index 848f88118ed32..bc21e9cd6c894 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice.php @@ -5,11 +5,9 @@ */ namespace Magento\Sales\Model\ResourceModel\Order; -use Magento\Framework\App\ResourceConnection; -use Magento\SalesSequence\Model\Manager; -use Magento\Sales\Model\ResourceModel\Attribute; +use Magento\Framework\DataObject; +use Magento\Framework\Model\AbstractModel; use Magento\Sales\Model\ResourceModel\EntityAbstract as SalesResource; -use Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot; use Magento\Sales\Model\Spi\InvoiceResourceInterface; /** @@ -37,10 +35,10 @@ protected function _construct() /** * Perform actions before object save * - * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object + * @param AbstractModel|DataObject $object * @return $this */ - protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) + protected function _beforeSave(AbstractModel $object) { /** @var \Magento\Sales\Model\Order\Invoice $object */ if (!$object->getOrderId() && $object->getOrder()) { @@ -50,4 +48,29 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) return parent::_beforeSave($object); } + + /** + * Calculate refunded amount for invoice + * + * @param int $invoiceId + * @param string $filed + * @return float + * @throws \InvalidArgumentException + */ + public function calculateRefundedAmount(int $invoiceId, string $filed): float + { + if (empty($filed)) { + throw new \InvalidArgumentException('The field param must be passed'); + } + + $select = $this->getConnection()->select(); + $select->from( + ['credit_memo' => $this->getTable('sales_creditmemo')], + ['total' => new \Zend_Db_Expr("SUM(credit_memo.{$filed})")] + )->where( + "credit_memo.invoice_id = ?", $invoiceId + ); + + return (float) $this->getConnection()->fetchOne($select); + } } diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontOrderShipmentsQtyShippedActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontOrderShipmentsQtyShippedActionGroup.xml new file mode 100644 index 0000000000000..0c3544f8944ed --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AssertStorefrontOrderShipmentsQtyShippedActionGroup.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="AssertStorefrontOrderShipmentsQtyShippedActionGroup"> + <annotations> + <description>Verify Customer Order Shipments Qty Shipped</description> + </annotations> + <arguments> + <argument name="expectedQtyShipped" type="string" defaultValue="0"/> + </arguments> + <grabTextFrom selector="{{StorefrontSalesOrderShipmentSection.salesOrderQtyShipped}}" stepKey="grabSalesOrderQtyShipped"/> + <assertEquals stepKey="assertOrderQtyShipped"> + <actualResult type="string">$grabSalesOrderQtyShipped</actualResult> + <expectedResult type="string">{{expectedQtyShipped}}</expectedResult> + </assertEquals> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/CancelOrderData.xml b/app/code/Magento/Sales/Test/Mftf/Data/CancelOrderData.xml new file mode 100644 index 0000000000000..d50a262a2f8b2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/CancelOrderData.xml @@ -0,0 +1,17 @@ +<?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="CancelOrder" type="CancelOrder"> + <var key="quote_id" entityKey="return" entityType="CustomerCart"/> + </entity> + +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Metadata/CancelOrderMeta.xml b/app/code/Magento/Sales/Test/Mftf/Metadata/CancelOrderMeta.xml new file mode 100644 index 0000000000000..c874b5a2118db --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Metadata/CancelOrderMeta.xml @@ -0,0 +1,17 @@ +<?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="CreateCancelOrder" dataType="CancelOrder" type="create" auth="adminOauth" url="V1/orders/{return}/cancel" method="POST"> + <contentType>application/json</contentType> + <object key="cartItem" dataType="CartItem"> + <field key="quote_id">string</field> + </object> + </operation> +</operations> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontSalesOrderShipmentSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontSalesOrderShipmentSection.xml new file mode 100644 index 0000000000000..e2e814efb9f02 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontSalesOrderShipmentSection.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="StorefrontSalesOrderShipmentSection"> + <element name="salesOrderQtyShipped" type="text" selector="//td[@data-th='Qty Shipped']"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml new file mode 100644 index 0000000000000..b086074132e85 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontVerifyOrderShipmentForDecimalQuantityTest.xml @@ -0,0 +1,104 @@ +<?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="StorefrontVerifyOrderShipmentForDecimalQuantityTest"> + <annotations> + <title value="Incorrect Quantity Shipped Displayed on order detail page on the front"/> + <stories value="Verify shipment quantity for decimal quantity at frontend order shipment tab"/> + <description value="Verify shipment quantity for decimal quantity at frontend order shipment tab"/> + <features value="Sales"/> + <testCaseId value="MC-39777"/> + <useCaseId value="MC-39353"/> + <severity value="MAJOR"/> + <group value="Sales"/> + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createSimpleCategory"/> + <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createSimpleCategory"/> + </createData> + <createData entity="Simple_US_Customer" stepKey="createSimpleUsCustomer"> + <field key="group_id">1</field> + </createData> + </before> + <after> + <!--Clear Filters--> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="ClearFiltersAfter"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearOrderListingFilters"/> + <deleteData createDataKey="createSimpleCategory" stepKey="deletePreReqCategory"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deletePreReqSimpleProduct"/> + <!--Logout from customer account--> + <amOnPage url="{{StorefrontCustomerLogoutPage.url}}" stepKey="logoutCustomerOne"/> + <waitForPageLoad stepKey="waitLogoutCustomerOne"/> + <deleteData createDataKey="createSimpleUsCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + <!--Step1. Login as admin. Go to Catalog > Products page. Filtering *prod1*. Open *prod1* to edit--> + <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin" /> + <actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="filterGroupedProductOptions"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + <!-- Step2. Update product Advanced Inventory Setting. + Set *Qty Uses Decimals* to *Yes* and *Enable Qty Increments* to *Yes* and *Qty Increments* to *2.14*. --> + <actionGroup ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup" stepKey="openProduct"/> + <actionGroup ref="AdminClickOnAdvancedInventoryLinkActionGroup" stepKey="clickOnAdvancedInventoryLink"/> + <actionGroup ref="AdminSetQtyUsesDecimalsConfigActionGroup" stepKey="setQtyUsesDecimalsConfig"> + <argument name="value" value="Yes"/> + </actionGroup> + <actionGroup ref="AdminSetEnableQtyIncrementsActionGroup" stepKey="setEnableQtyIncrements"> + <argument name="value" value="Yes"/> + </actionGroup> + <actionGroup ref="AdminSetQtyIncrementsForProductActionGroup" stepKey="setQtyIncrementsValue"> + <argument name="qty" value="2.14"/> + </actionGroup> + <actionGroup ref="AdminSetMinAllowedQtyForProductActionGroup" stepKey="fillMiniAllowedQty"> + <argument name="qty" value="2.14"/> + </actionGroup> + <actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickOnDoneButton"/> + + <!--Step3. Save the product--> + <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickOnSaveButton"/> + <!--Step4. Open *Customer view* (Go to *Store Front*). Open *prod1* page (Find via search and click on product name) --> + <!--Step5. Log in to Storefront as Customer--> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="signUpNewUser"> + <argument name="Customer" value="$$createSimpleUsCustomer$$"/> + </actionGroup> + <!--Step6. Go to product page--> + <amOnPage url="$$createSimpleProduct.custom_attributes[url_key]$$.html" stepKey="navigateToSimpleProductPage"/> + <waitForPageLoad stepKey="waitForCatalogPageLoad"/> + <!--Step7. Add Product to Shopping Cart--> + <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage"> + <argument name="productName" value="$$createSimpleProduct.name$$"/> + </actionGroup> + + <!--Step8. Navigate to checkout--> + <actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="openCheckoutPage"/> + <!--Step9. Click next button to open payment section--> + <actionGroup ref="StorefrontCheckoutClickNextButtonActionGroup" stepKey="clickNext"/> + <!--Step10. Click place order--> + <actionGroup ref="ClickPlaceOrderActionGroup" stepKey="placeOrder"/> + <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/> + <!--Step11. Go to admin Order page for newly created order--> + <actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrdersGridById"> + <argument name="orderId" value="{$grabOrderNumber}"/> + </actionGroup> + + <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipAction"/> + <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="clickSubmitShipment"/> + + <actionGroup ref="StorefrontNavigateToCustomerOrdersHistoryPageActionGroup" stepKey="goToOrderHistoryPage"/> + <!--Step12. Go to Customer Order Shipment Page and Checking the correctness of displayed Qty Shipped --> + <amOnPage url="{{StorefrontCustomerOrderShipmentPage.url({$grabOrderNumber})}}" stepKey="amOnOrderShipmentPage"/> + <waitForPageLoad time="30" stepKey="waitForOrderShipmentsPageLoad"/> + <actionGroup ref="AssertStorefrontOrderShipmentsQtyShippedActionGroup" stepKey="verifyAssertOrderShipments"> + <argument name="expectedQtyShipped" value="2.14"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php index 94346fc1b7a28..f6d7c6fdba60a 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php @@ -17,6 +17,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Class to test Collecting credit memo taxes + */ class TaxTest extends TestCase { /** @@ -44,6 +47,9 @@ class TaxTest extends TestCase */ protected $invoice; + /** + * @inheritdoc + */ protected function setUp(): void { $this->objectManager = new ObjectManager($this); @@ -186,8 +192,10 @@ public function collectDataProvider() 'base_shipping_amount' => 30, 'tax_amount' => 0.82, 'base_tax_amount' => 0.82, - 'invoice' => new MagentoObject( + 'invoice' => $this->createInvoiceMock( [ + 'tax_amount' => 24.33, + 'base_tax_amount' => 24.33, 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, 'shipping_discount_tax_compensation_amount' => 0, @@ -275,8 +283,10 @@ public function collectDataProvider() 'base_shipping_amount' => 30, 'tax_amount' => 0.82 * $currencyRatio, 'base_tax_amount' => 0.82, - 'invoice' => new MagentoObject( + 'invoice' => $this->createInvoiceMock( [ + 'tax_amount' => 24.33 * $currencyRatio, + 'base_tax_amount' => 24.33, 'shipping_tax_amount' => 2.45 * $currencyRatio, 'base_shipping_tax_amount' => 2.45, 'shipping_discount_tax_compensation_amount' => 0, @@ -350,8 +360,10 @@ public function collectDataProvider() 'base_shipping_amount' => 30, 'tax_amount' => 1.65, 'base_tax_amount' => 1.65, - 'invoice' => new MagentoObject( + 'invoice' => $this->createInvoiceMock( [ + 'tax_amount' => 11.14, + 'base_tax_amount' => 11.14, 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, 'shipping_discount_tax_compensation_amount' => 0, @@ -426,8 +438,10 @@ public function collectDataProvider() 'base_shipping_amount' => 0, 'tax_amount' => 0.82, 'base_tax_amount' => 0.82, - 'invoice' => new MagentoObject( + 'invoice' => $this->createInvoiceMock( [ + 'tax_amount' => 16.09, + 'base_tax_amount' => 16.09, 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, 'shipping_discount_tax_compensation_amount' => 0, @@ -507,14 +521,6 @@ public function collectDataProvider() 'base_shipping_amount' => 0, 'tax_amount' => 0.76, 'base_tax_amount' => 0.76, - 'invoice' => new MagentoObject( - [ - 'shipping_tax_amount' => 0, - 'base_shipping_tax_amount' => 0, - 'shipping_discount_tax_compensation_amount' => 0, - 'base_shipping_discount_tax_compensation_amount' => 0, - ] - ), ], ], 'expected_results' => [ @@ -581,8 +587,10 @@ public function collectDataProvider() 'base_grand_total' => 60.82, 'tax_amount' => 0.82, 'base_tax_amount' => 0.82, - 'invoice' => new MagentoObject( + 'invoice' => $this->createInvoiceMock( [ + 'tax_amount' => 16.09, + 'base_tax_amount' => 16.09, 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, 'shipping_discount_tax_compensation_amount' => 0, @@ -712,14 +720,6 @@ public function collectDataProvider() 'base_shipping_amount' => 0, 'tax_amount' => 0, 'base_tax_amount' => 0, - 'invoice' => new MagentoObject( - [ - 'shipping_tax_amount' => 0, - 'base_shipping_tax_amount' => 0, - 'shipping_discount_tax_compensation_amount' => 0, - 'base_shipping_discount_tax_compensation_amount' => 0, - ] - ), ], ], 'expected_results' => [ @@ -779,4 +779,40 @@ protected function getCreditmemoItem($creditmemoItemData) $creditmemoItem->setData('qty', $creditmemoItemData['qty']); return $creditmemoItem; } + + /** + * Create invoice mock object + * + * @param array $data + * @return MockObject|Invoice + */ + private function createInvoiceMock(array $data): MockObject + { + /** @var MockObject|Invoice $invoice */ + $invoice = $this->getMockBuilder(Invoice::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->addMethods(['getBaseShippingDiscountTaxCompensationAmount']) + ->onlyMethods([ + 'getTaxAmount', + 'getBaseTaxAmount', + 'getShippingTaxAmount', + 'getBaseShippingTaxAmount', + 'getShippingDiscountTaxCompensationAmount' + ]) + ->getMock(); + + $invoice->method('getTaxAmount')->willReturn($data['tax_amount'] ?? 0); + $invoice->method('getBaseTaxAmount')->willReturn($data['base_tax_amount'] ?? 0); + $invoice->method('getShippingTaxAmount')->willReturn($data['shipping_tax_amount'] ?? 0); + $invoice->method('getBaseShippingTaxAmount')->willReturn($data['base_shipping_tax_amount'] ?? 0); + $invoice->method('getShippingDiscountTaxCompensationAmount') + ->willReturn($data['shipping_discount_tax_compensation_amount'] ?? 0); + $invoice->method('getBaseShippingDiscountTaxCompensationAmount') + ->willReturn($data['base_shipping_discount_tax_compensation_amount'] ?? 0); + + return $invoice; + } } diff --git a/app/code/Magento/Sales/ViewModel/Header/LogoPathResolver.php b/app/code/Magento/Sales/ViewModel/Header/LogoPathResolver.php new file mode 100644 index 0000000000000..c58654e160749 --- /dev/null +++ b/app/code/Magento/Sales/ViewModel/Header/LogoPathResolver.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\ViewModel\Header; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Theme\ViewModel\Block\Html\Header\LogoPathResolverInterface; +use Magento\Framework\View\Element\Block\ArgumentInterface; +use Magento\Sales\Model\Order; +use Magento\Framework\Registry; + +/** + * Class for resolving logo path + */ +class LogoPathResolver implements LogoPathResolverInterface, ArgumentInterface +{ + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Core registry + * + * @var Registry + */ + private $coreRegistry; + + /** + * @param ScopeConfigInterface $scopeConfig + * @param Registry $registry + */ + public function __construct( + ScopeConfigInterface $scopeConfig, + Registry $registry + ) { + $this->scopeConfig = $scopeConfig; + $this->coreRegistry = $registry; + } + + /** + * Return logo image path + * + * @return string|null + */ + public function getPath(): ?string + { + $path = null; + $storeId = null; + $order = $this->coreRegistry->registry('current_order'); + if ($order instanceof Order) { + $storeId = $order->getStoreId(); + } + $storeLogoPath = $this->scopeConfig->getValue( + 'sales/identity/logo_html', + ScopeInterface::SCOPE_STORE, + $storeId + ); + if ($storeLogoPath !== null) { + $path = 'sales/store/logo_html/' . $storeLogoPath; + } + return $path; + } +} diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml index 4410a6fc4a9a2..8a52e65a9f70c 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml @@ -44,5 +44,10 @@ <block class="Magento\Sales\Block\Order\Info" as="sales.order.print.info" name="sales.order.print.info" template="Magento_Sales::order/info.phtml"/> </referenceContainer> <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Theme::template.phtml"/> + <referenceBlock name="logo"> + <arguments> + <argument name="logoPathResolver" xsi:type="object">Magento\Sales\ViewModel\Header\LogoPathResolver</argument> + </arguments> + </referenceBlock> </body> </page> diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml index 0021eeede4f2b..317ee419f6d96 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printcreditmemo.xml @@ -28,5 +28,10 @@ </block> </referenceContainer> <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Theme::template.phtml"/> + <referenceBlock name="logo"> + <arguments> + <argument name="logoPathResolver" xsi:type="object">Magento\Sales\ViewModel\Header\LogoPathResolver</argument> + </arguments> + </referenceBlock> </body> </page> diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml index 0272286696e24..e0bb15bc0e7fd 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printinvoice.xml @@ -35,5 +35,10 @@ </block> </referenceContainer> <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Theme::template.phtml"/> + <referenceBlock name="logo"> + <arguments> + <argument name="logoPathResolver" xsi:type="object">Magento\Sales\ViewModel\Header\LogoPathResolver</argument> + </arguments> + </referenceBlock> </body> </page> diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml index 30053b41a96a9..b7940c0d406cc 100644 --- a/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml +++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_printshipment.xml @@ -20,5 +20,10 @@ </block> </referenceContainer> <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Theme::template.phtml"/> + <referenceBlock name="logo"> + <arguments> + <argument name="logoPathResolver" xsi:type="object">Magento\Sales\ViewModel\Header\LogoPathResolver</argument> + </arguments> + </referenceBlock> </body> </page> diff --git a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml index 6c7567a8cd14b..d2caa1a2ce935 100644 --- a/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml +++ b/app/code/Magento/Sales/view/frontend/templates/order/shipment/items/renderer/default.phtml @@ -42,5 +42,5 @@ <td class="col sku" data-th="<?= $block->escapeHtml(__('SKU')) ?>"> <?= /* @noEscape */ $block->prepareSku($block->getSku()) ?> </td> - <td class="col qty" data-th="<?= $block->escapeHtml(__('Qty Shipped')) ?>"><?= (int) $_item->getQty() ?></td> + <td class="col qty" data-th="<?= $block->escapeHtml(__('Qty Shipped')) ?>"><?= (float) $_item->getQty() ?></td> </tr> diff --git a/app/code/Magento/Theme/Block/Html/Header/Logo.php b/app/code/Magento/Theme/Block/Html/Header/Logo.php index 792ee95de4995..3c43e5bfc6fe1 100644 --- a/app/code/Magento/Theme/Block/Html/Header/Logo.php +++ b/app/code/Magento/Theme/Block/Html/Header/Logo.php @@ -6,6 +6,8 @@ namespace Magento\Theme\Block\Html\Header; +use Magento\Theme\ViewModel\Block\Html\Header\LogoPathResolverInterface; + /** * Logo page header block * @@ -124,16 +126,16 @@ public function getLogoHeight() */ protected function _getLogoUrl() { - $folderName = \Magento\Config\Model\Config\Backend\Image\Logo::UPLOAD_DIR; - $storeLogoPath = $this->_scopeConfig->getValue( - 'design/header/logo_src', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ); - $path = $folderName . '/' . $storeLogoPath; + $path = null; + /** @var LogoPathResolverInterface $logoPathResolver */ + $logoPathResolver = $this->getData('logoPathResolver'); + if ($logoPathResolver instanceof LogoPathResolverInterface) { + $path = $logoPathResolver->getPath(); + } $logoUrl = $this->_urlBuilder ->getBaseUrl(['_type' => \Magento\Framework\UrlInterface::URL_TYPE_MEDIA]) . $path; - if ($storeLogoPath !== null && $this->_isFile($path)) { + if ($path !== null && $this->_isFile($path)) { $url = $logoUrl; } elseif ($this->getLogoFile()) { $url = $this->getViewFileUrl($this->getLogoFile()); diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/Header/LogoTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/Header/LogoTest.php index 1978362810763..a5095674a4673 100644 --- a/app/code/Magento/Theme/Test/Unit/Block/Html/Header/LogoTest.php +++ b/app/code/Magento/Theme/Test/Unit/Block/Html/Header/LogoTest.php @@ -7,6 +7,7 @@ namespace Magento\Theme\Test\Unit\Block\Html\Header; +use Magento\Theme\ViewModel\Block\Html\Header\LogoPathResolverInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\Read; @@ -25,11 +26,11 @@ public function testGetLogoSrc() { $filesystem = $this->createMock(Filesystem::class); $mediaDirectory = $this->createMock(Read::class); - $scopeConfig = $this->getMockForAbstractClass(ScopeConfigInterface::class); + $logoPathResolver = $this->getMockForAbstractClass(LogoPathResolverInterface::class); $urlBuilder = $this->getMockForAbstractClass(UrlInterface::class); - $scopeConfig->expects($this->once())->method('getValue')->willReturn('default/image.gif'); + $logoPathResolver->expects($this->once())->method('getPath')->willReturn('logo/default/image.gif'); $urlBuilder->expects( $this->once() )->method( @@ -46,7 +47,7 @@ public function testGetLogoSrc() $objectManager = new ObjectManager($this); $arguments = [ - 'scopeConfig' => $scopeConfig, + 'data' => ['logoPathResolver' => $logoPathResolver], 'urlBuilder' => $urlBuilder, 'fileStorageHelper' => $helper, 'filesystem' => $filesystem, diff --git a/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolver.php b/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolver.php new file mode 100644 index 0000000000000..1a10fe9177320 --- /dev/null +++ b/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolver.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\ViewModel\Block\Html\Header; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Config\Model\Config\Backend\Image\Logo; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\View\Element\Block\ArgumentInterface; + +/** + * Class for resolving logo path + */ +class LogoPathResolver implements LogoPathResolverInterface, ArgumentInterface +{ + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct( + ScopeConfigInterface $scopeConfig + ) { + $this->scopeConfig = $scopeConfig; + } + + /** + * Return logo image path + * + * @return string|null + */ + public function getPath(): ?string + { + $path = null; + $storeLogoPath = $this->scopeConfig->getValue( + 'design/header/logo_src', + ScopeInterface::SCOPE_STORE + ); + if ($storeLogoPath !== null) { + $path = Logo::UPLOAD_DIR . '/' . $storeLogoPath; + } + return $path; + } +} diff --git a/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolverInterface.php b/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolverInterface.php new file mode 100644 index 0000000000000..3ac8442aa0ea7 --- /dev/null +++ b/app/code/Magento/Theme/ViewModel/Block/Html/Header/LogoPathResolverInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Theme\ViewModel\Block\Html\Header; + +/** + * Interface for resolving logo path + */ +interface LogoPathResolverInterface +{ + /** + * Return logo image path + * + * @return null|string + */ + public function getPath(): ?string; +} diff --git a/app/code/Magento/Theme/view/frontend/layout/default.xml b/app/code/Magento/Theme/view/frontend/layout/default.xml index bf76933b356c0..f3e57b12150c9 100644 --- a/app/code/Magento/Theme/view/frontend/layout/default.xml +++ b/app/code/Magento/Theme/view/frontend/layout/default.xml @@ -51,7 +51,11 @@ </container> </container> <container name="header-wrapper" label="Page Header" as="header-wrapper" htmlTag="div" htmlClass="header content"> - <block class="Magento\Theme\Block\Html\Header\Logo" name="logo"/> + <block class="Magento\Theme\Block\Html\Header\Logo" name="logo"> + <arguments> + <argument name="logoPathResolver" xsi:type="object">Magento\Theme\ViewModel\Block\Html\Header\LogoPathResolver</argument> + </arguments> + </block> </container> </referenceContainer> <referenceContainer name="page.top"> diff --git a/app/code/Magento/UrlRewrite/Model/UrlRewrite.php b/app/code/Magento/UrlRewrite/Model/UrlRewrite.php index 5f29008621c1a..cbefcd4c75597 100644 --- a/app/code/Magento/UrlRewrite/Model/UrlRewrite.php +++ b/app/code/Magento/UrlRewrite/Model/UrlRewrite.php @@ -8,7 +8,17 @@ namespace Magento\UrlRewrite\Model; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\EntityManager\EventManager; +use Magento\Framework\Indexer\CacheContext; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\Context; +use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\Registry; use Magento\Framework\Serialize\Serializer\Json; +use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteService; /** * UrlRewrite model class @@ -27,32 +37,65 @@ * @method UrlRewrite setStoreId($value) * @method UrlRewrite setDescription($value) */ -class UrlRewrite extends \Magento\Framework\Model\AbstractModel +class UrlRewrite extends AbstractModel { /** * @var Json */ private $serializer; + /** + * @var CacheContext|mixed|null + */ + private $cacheContext; + + /** + * @var EventManager|mixed|null + */ + private $eventManager; + + /** + * @var array + */ + private $entityToCacheTagMap; + + /** + * @var UrlFinderInterface + */ + private $urlFinder; + /** * UrlRewrite constructor. * - * @param \Magento\Framework\Model\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource - * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection + * @param Context $context + * @param Registry $registry + * @param AbstractResource|null $resource + * @param AbstractDb|null $resourceCollection * @param array $data - * @param Json $serializer + * @param Json|null $serializer + * @param CacheContext|null $cacheContext + * @param EventManager|null $eventManager + * @param UrlFinderInterface|null $urlFinder + * @param array $entityToCacheTagMap */ public function __construct( - \Magento\Framework\Model\Context $context, - \Magento\Framework\Registry $registry, - \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, + Context $context, + Registry $registry, + AbstractResource $resource = null, + AbstractDb $resourceCollection = null, array $data = [], - Json $serializer = null - ) { + Json $serializer = null, + CacheContext $cacheContext = null, + EventManager $eventManager = null, + UrlFinderInterface $urlFinder = null, + array $entityToCacheTagMap = [] + ) + { $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class); + $this->cacheContext = $cacheContext ?: ObjectManager::getInstance()->get(CacheContext::class); + $this->eventManager = $eventManager ?: ObjectManager::getInstance()->get(EventManager::class); + $this->urlFinder = $urlFinder ?: ObjectManager::getInstance()->get(UrlFinderInterface::class); + $this->entityToCacheTagMap = $entityToCacheTagMap; parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -63,8 +106,8 @@ public function __construct( */ protected function _construct() { - $this->_init(\Magento\UrlRewrite\Model\ResourceModel\UrlRewrite::class); - $this->_collectionName = \Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection::class; + $this->_init(ResourceModel\UrlRewrite::class); + $this->_collectionName = UrlRewriteCollection::class; } /** @@ -92,4 +135,101 @@ public function setMetadata($metadata) } return $this->setData(\Magento\UrlRewrite\Service\V1\Data\UrlRewrite::METADATA, $metadata); } + + /** + * Gets final target UrlRewrite for custom rewrite record + * + * @param string $path + * @param int $storeId + * @return UrlRewriteService|null + */ + private function getFinalTargetUrlRewrite(string $path, int $storeId): ?UrlRewriteService + { + $urlRewriteTarget = $this->urlFinder->findOneByData( + [ + 'request_path' => $path, + 'store_id' => $storeId + ] + ); + + while ( + $urlRewriteTarget && + $urlRewriteTarget->getTargetPath() !== $urlRewriteTarget->getRequestPath() && + $urlRewriteTarget->getRedirectType() > 0 + ) { + $urlRewriteTarget = $this->urlFinder->findOneByData( + [ + 'request_path' => $urlRewriteTarget->getTargetPath(), + 'store_id' => $urlRewriteTarget->getStoreId() + ] + ); + } + + return $urlRewriteTarget; + } + + /** + * Clean the cache for entities affected by current rewrite + */ + public function cleanEntitiesCache() + { + if (!$this->isEmpty()) { + if ($this->getEntityType() === Rewrite::ENTITY_TYPE_CUSTOM) { + $urlRewrite = $this->getFinalTargetUrlRewrite( + $this->getTargetPath(), + (int)$this->getStoreId() + ); + + if ($urlRewrite) { + $this->cleanCacheForEntity($urlRewrite->getEntityType(), (int) $urlRewrite->getEntityId()); + } + + if ($this->getOrigData() && $this->getOrigData('target_path') !== $this->getTargetPath()) { + $origUrlRewrite = $this->getFinalTargetUrlRewrite( + $this->getOrigData('target_path'), + (int)$this->getOrigData('store_id') + ); + + if ($origUrlRewrite) { + $this->cleanCacheForEntity($origUrlRewrite->getEntityType(), (int) $origUrlRewrite->getEntityId()); + } + } + } else { + $this->cleanCacheForEntity($this->getEntityType(), (int) $this->getEntityId()); + } + } + } + + /** + * Clean cache for specified entity type by id + * + * @param string $entityType + * @param int $entityId + */ + private function cleanCacheForEntity(string $entityType, int $entityId) + { + if (array_key_exists($entityType, $this->entityToCacheTagMap)) { + $cacheKey = $this->entityToCacheTagMap[$entityType]; + $this->cacheContext->registerEntities($cacheKey, [$entityId]); + $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]); + } + } + + /** + * @inheritdoc + */ + public function afterDelete() + { + $this->_getResource()->addCommitCallback([$this, 'cleanEntitiesCache']); + return parent::afterDelete(); + } + + /** + * @inheritdoc + */ + public function afterSave() + { + $this->_getResource()->addCommitCallback([$this, 'cleanEntitiesCache']); + return parent::afterSave(); + } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogGraphQl/PriceRangeTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogGraphQl/PriceRangeTest.php new file mode 100644 index 0000000000000..81b08f28431a6 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogGraphQl/PriceRangeTest.php @@ -0,0 +1,175 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\CatalogGraphQl; + +use Magento\GraphQl\GetCustomerAuthenticationHeader; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test class to verify catalog price rule is applied for + * tier prices for different customer groups. + */ +class PriceRangeTest extends GraphQlAbstract +{ + /** + * @var ObjectManager|null + */ + private $objectManager; + + /** + * @var GetCustomerAuthenticationHeader + */ + private $getCustomerAuthenticationHeader; + + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->getCustomerAuthenticationHeader = $this->objectManager->get(GetCustomerAuthenticationHeader::class); + } + + /** + * Test for checking if catalog rule price has been applied for all customer group + * + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php + */ + public function testCheckIfCatalogRuleIsAppliedForTierPriceForAllGroups(): void + { + $productSku = 'simple'; + $query = $this->getProductSearchQuery($productSku); + + $response = $this->graphQlQuery($query); + + $this->assertNotEmpty($response['products']); + $priceRange = $response['products']['items'][0]['price_range']; + $this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']); + $this->assertEquals(7.5, $priceRange['minimum_price']['final_price']['value']); + $this->assertEquals(2.5, $priceRange['minimum_price']['discount']['amount_off']); + $this->assertEquals(25, $priceRange['minimum_price']['discount']['percent_off']); + $this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']); + $this->assertEquals(7.5, $priceRange['maximum_price']['final_price']['value']); + $this->assertEquals(2.5, $priceRange['maximum_price']['discount']['amount_off']); + $this->assertEquals(25, $priceRange['maximum_price']['discount']['percent_off']); + } + + /** + * Test for checking if catalog rule price has been applied for registered customer + * + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group.php + * @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php + */ + public function testCheckIfCatalogRuleIsAppliedForTierPriceForRegisteredCustomer(): void + { + $productSku = 'simple'; + $query = $this->getProductSearchQuery($productSku); + $response = $this->graphQlQuery( + $query, + [], + '', + $this->getCustomerAuthenticationHeader->execute('customer@example.com', 'password') + ); + + $this->assertNotEmpty($response['products']); + $priceRange = $response['products']['items'][0]['price_range']; + $this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']); + $this->assertEquals(5, $priceRange['minimum_price']['final_price']['value']); + $this->assertEquals(5, $priceRange['minimum_price']['discount']['amount_off']); + $this->assertEquals(50, $priceRange['minimum_price']['discount']['percent_off']); + $this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']); + $this->assertEquals(5, $priceRange['maximum_price']['final_price']['value']); + $this->assertEquals(5, $priceRange['maximum_price']['discount']['amount_off']); + $this->assertEquals(50, $priceRange['maximum_price']['discount']['percent_off']); + } + + /** + * Test for checking if catalog rule price has been applied for guest + * + * @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php + * @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php + */ + public function testCheckIfCatalogRuleIsAppliedForTierPriceForGuest(): void + { + $productSku = 'simple'; + $query = $this->getProductSearchQuery($productSku); + $response = $this->graphQlQuery($query); + + $this->assertNotEmpty($response['products']); + $priceRange = $response['products']['items'][0]['price_range']; + $this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']); + $this->assertEquals(9, $priceRange['minimum_price']['final_price']['value']); + $this->assertEquals(1, $priceRange['minimum_price']['discount']['amount_off']); + $this->assertEquals(10, $priceRange['minimum_price']['discount']['percent_off']); + $this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']); + $this->assertEquals(9, $priceRange['maximum_price']['final_price']['value']); + $this->assertEquals(1, $priceRange['maximum_price']['discount']['amount_off']); + $this->assertEquals(10, $priceRange['maximum_price']['discount']['percent_off']); + } + + /** + * Get a query which user filter for product sku and returns price_tiers + * + * @param string $productSku + * @return string + */ + private function getProductSearchQuery(string $productSku): string + { + return <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) { + items { + name + sku + price_range { + minimum_price { + regular_price { + value + currency + } + final_price { + value + currency + } + discount { + amount_off + percent_off + } + } + maximum_price { + regular_price { + value + currency + } + final_price { + value + currency + } + discount { + amount_off + percent_off + } + } + } + price_tiers{ + discount{ + amount_off + percent_off + } + final_price{ + value + } + quantity + } + } + } +} +QUERY; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php index 7aed048f1c4ce..4a4b617d7c28e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php @@ -7,8 +7,14 @@ namespace Magento\GraphQl\UrlRewrite; +use Magento\Framework\Exception\AlreadyExistsException; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +use Magento\UrlRewrite\Model\ResourceModel\UrlRewrite as UrlRewriteResourceModel; +use Magento\UrlRewrite\Model\UrlFinderInterface; +use Magento\UrlRewrite\Model\UrlRewrite as UrlRewriteModel; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteService; /** * Test the GraphQL endpoint's URLResolver query to verify canonical URL's are correctly returned. @@ -20,7 +26,7 @@ class UrlResolverTest extends GraphQlAbstract protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); } /** @@ -50,4 +56,175 @@ public function testNonExistentEntityUrlRewrite() ); $this->graphQlQuery($query); } + + /** + * Test for url rewrite to clean cache on rewrites update + * + * @magentoApiDataFixture Magento/Catalog/_files/product_with_category.php + * @magentoApiDataFixture Magento/Cms/_files/pages.php + * + * @dataProvider urlRewriteEntitiesDataProvider + * @param string $requestPath + * @throws AlreadyExistsException + */ + public function testUrlRewriteCleansCacheOnChange(string $requestPath) + { + + /** @var UrlRewriteResourceModel $urlRewriteResourceModel */ + $urlRewriteResourceModel = $this->objectManager->create(UrlRewriteResourceModel::class); + $storeId = 1; + $query = function ($requestUrl) { + return <<<QUERY +{ + urlResolver(url:"{$requestUrl}") + { + id + entity_uid + relative_url + type + redirectCode + } +} +QUERY; + }; + + // warming up urlResolver API response cache for entity and validate proper response + $apiResponse = $this->graphQlQuery($query($requestPath)); + $this->assertEquals($requestPath, $apiResponse['urlResolver']['relative_url']); + + $urlRewrite = $this->getUrlRewriteModelByRequestPath($requestPath, $storeId); + + // renaming entity request path and validating that API will not return cached response + $urlRewrite->setRequestPath('test' . $requestPath); + $urlRewriteResourceModel->save($urlRewrite); + $apiResponse = $this->graphQlQuery($query($requestPath)); + $this->assertNull($apiResponse['urlResolver']); + + // rolling back changes + $urlRewrite->setRequestPath($requestPath); + $urlRewriteResourceModel->save($urlRewrite); + } + + public function urlRewriteEntitiesDataProvider(): array + { + return [ + [ + 'simple-product-in-stock.html' + ], + [ + 'category-1.html' + ], + [ + 'page100' + ] + ]; + } + + /** + * Test for custom url rewrite to clean cache on update combinations + * + * @magentoApiDataFixture Magento/Catalog/_files/product_with_category.php + * @magentoApiDataFixture Magento/Cms/_files/pages.php + * + * @throws AlreadyExistsException + */ + public function testUrlRewriteCleansCacheForCustomRewrites() + { + + /** @var UrlRewriteResourceModel $urlRewriteResourceModel */ + $urlRewriteResourceModel = $this->objectManager->create(UrlRewriteResourceModel::class); + $storeId = 1; + $query = function ($requestUrl) { + return <<<QUERY +{ + urlResolver(url:"{$requestUrl}") + { + id + entity_uid + relative_url + type + redirectCode + } +} +QUERY; + }; + + $customRequestPath = 'test.html'; + $customSecondRequestPath = 'test2.html'; + $entitiesRequestPaths = [ + 'simple-product-in-stock.html', + 'category-1.html', + 'page100' + ]; + + // create custom url rewrite + $urlRewrite = $this->objectManager->create(UrlRewriteModel::class); + $urlRewrite->setEntityType('custom') + ->setRedirectType(302) + ->setStoreId($storeId) + ->setDescription(null) + ->setIsAutogenerated(0); + + // create second custom url rewrite and target it to previous one to check + // if proper final target url will be resolved + $secondUrlRewrite = $this->objectManager->create(UrlRewriteModel::class); + $secondUrlRewrite->setEntityType('custom') + ->setRedirectType(302) + ->setStoreId($storeId) + ->setRequestPath($customSecondRequestPath) + ->setTargetPath($customRequestPath) + ->setDescription(null) + ->setIsAutogenerated(0); + $urlRewriteResourceModel->save($secondUrlRewrite); + + foreach ($entitiesRequestPaths as $entityRequestPath) { + // updating custom rewrite for each entity + $urlRewrite->setRequestPath($customRequestPath) + ->setTargetPath($entityRequestPath); + $urlRewriteResourceModel->save($urlRewrite); + + // confirm that API returns non-cached response for the first custom rewrite + $apiResponse = $this->graphQlQuery($query($customRequestPath)); + $this->assertEquals($entityRequestPath, $apiResponse['urlResolver']['relative_url']); + + // confirm that API returns non-cached response for the second custom rewrite + $apiResponse = $this->graphQlQuery($query($customSecondRequestPath)); + $this->assertEquals($entityRequestPath, $apiResponse['urlResolver']['relative_url']); + } + + $urlRewriteResourceModel->delete($secondUrlRewrite); + + // delete custom rewrite and validate that API will not return cached response + $urlRewriteResourceModel->delete($urlRewrite); + $apiResponse = $this->graphQlQuery($query($customRequestPath)); + $this->assertNull($apiResponse['urlResolver']); + } + + /** + * Return UrlRewrite model instance by request_path + * + * @param string $requestPath + * @param int $storeId + * @return UrlRewriteModel + */ + private function getUrlRewriteModelByRequestPath(string $requestPath, int $storeId): UrlRewriteModel + { + /** @var UrlFinderInterface $urlFinder */ + $urlFinder = $this->objectManager->get(UrlFinderInterface::class); + + /** @var UrlRewriteService $urlRewriteService */ + $urlRewriteService = $urlFinder->findOneByData( + [ + 'request_path' => $requestPath, + 'store_id' => $storeId + ] + ); + + /** @var UrlRewriteModel $urlRewrite */ + $urlRewrite = $this->objectManager->create(UrlRewriteModel::class); + $urlRewrite->load($urlRewriteService->getUrlRewriteId()); + + return $urlRewrite; + } + } 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 1054706819e95..42d21afae8274 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartItemRepositoryTest.php @@ -326,7 +326,7 @@ public function updateItemDataProvider(): array 'use_config_backorders' => 0, 'backorders' => Stock::BACKORDERS_NO, ], - 'This product is out of stock.' + 'There are no source items with the in stock status' ], [ [ diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/ExtendedTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/ExtendedTest.php index 328a85ffd51ad..6d3761fdfcb79 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/ExtendedTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/ExtendedTest.php @@ -5,34 +5,44 @@ */ namespace Magento\Backend\Block\Widget\Grid; +use Laminas\Stdlib\Parameters; +use Magento\Backend\Block\Template\Context; +use Magento\Framework\Data\Collection; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + /** * @magentoAppArea adminhtml */ -class ExtendedTest extends \PHPUnit\Framework\TestCase +class ExtendedTest extends TestCase { /** - * @var \Magento\Backend\Block\Widget\Grid\Extended + * @var Extended */ protected $_block; /** - * @var \Magento\Framework\View\LayoutInterface + * @var LayoutInterface */ protected $_layoutMock; + /** + * @inheritDoc + */ protected function setUp(): void { parent::setUp(); - $this->_layoutMock = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class + $this->_layoutMock = Bootstrap::getObjectManager()->get( + LayoutInterface::class ); - $context = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Backend\Block\Template\Context::class, + $context = Bootstrap::getObjectManager()->create( + Context::class, ['layout' => $this->_layoutMock] ); $this->_block = $this->_layoutMock->createBlock( - \Magento\Backend\Block\Widget\Grid\Extended::class, + Extended::class, 'grid', ['context' => $context] ); @@ -47,7 +57,7 @@ protected function setUp(): void public function testAddColumnAddsChildToColumnSet() { $this->assertInstanceOf( - \Magento\Backend\Block\Widget\Grid\Column::class, + Column::class, $this->_block->getColumnSet()->getChildBlock('column1') ); $this->assertCount(2, $this->_block->getColumnSet()->getChildNames()); @@ -84,4 +94,32 @@ public function testGetMainButtonsHtmlReturnsEmptyStringIfFiltersArentVisible() $this->_block->setFilterVisibility(false); $this->assertEquals('', $this->_block->getMainButtonsHtml()); } + + /** + * Checks that template does not have redundant div close tag + * + * @return void + */ + public function testExtendedTemplateMarkup(): void + { + $mockCollection = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->_block->setCollection($mockCollection); + $this->_block->getRequest() + ->setQuery( + Bootstrap::getObjectManager() + ->create( + Parameters::class, + [ + 'values' => [ + 'ajax' => true + ] + ] + ) + ); + $html = $this->_block->getHtml(); + $html = str_replace(["\n", " "], '', $html); + $this->assertStringEndsWith("</table></div>", $html); + } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Pricing/Price/FinalPriceTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Pricing/Price/FinalPriceTest.php new file mode 100644 index 0000000000000..6b1ab58035568 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/Pricing/Price/FinalPriceTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Pricing\Price; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * 'Final Price' model integration tests. + * + * @magentoDbIsolation disabled + */ +class FinalPriceTest extends TestCase +{ + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + } + + /** + * Check minimal and maximal prices are calculated correctly for Bundle product selections with Tier Prices. + * + * @return void + * @magentoDataFixture Magento/Bundle/_files/bundle_product_with_tier_price_selections.php + */ + public function testGetPriceForBundleSelectionsWithTierPrices(): void + { + $priceModel = $this->getPriceModel('bundle_with_tier_price_selections'); + $this->assertEquals(15.0, $priceModel->getMinimalPrice()->getValue()); + $this->assertEquals(45.0, $priceModel->getMaximalPrice()->getValue()); + } + + /** + * Create and retrieve Price Model for provided Product SKU. + * + * @param string $productSku + * @return FinalPrice + */ + private function getPriceModel(string $productSku): FinalPrice + { + $bundleProduct = $this->productRepository->get($productSku); + + return $this->objectManager->create( + FinalPrice::class, + [ + 'saleableItem' => $bundleProduct, + 'quantity' => 0., + ] + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections.php new file mode 100644 index 0000000000000..5ef6daa5d11da --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections.php @@ -0,0 +1,81 @@ +<?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\ProductInterfaceFactory; +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\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Bundle\Model\PrepareBundleLinks; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/three_simple_products_with_tier_price.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var PrepareBundleLinks $prepareBundleLinks */ +$prepareBundleLinks = $objectManager->get(PrepareBundleLinks::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$defaultWebsiteId = $storeManager->getWebsite('base')->getId(); + +$bundleProduct = $productFactory->create(); +$bundleProduct->setTypeId(Type::TYPE_BUNDLE) + ->setAttributeSetId($bundleProduct->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Bundle Product') + ->setSku('bundle_with_tier_price_selections') + ->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' => 'simple_1', + 'selection_qty' => 3, + ], + [ + 'sku' => 'simple_2', + 'selection_qty' => 3, + ], + [ + 'sku' => 'simple_3', + 'selection_qty' => 3, + ], + ] +]; +$bundleProduct = $prepareBundleLinks->execute($bundleProduct, $bundleOptionsData, $bundleSelectionsData); +$productRepository->save($bundleProduct); diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections_rollback.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections_rollback.php new file mode 100644 index 0000000000000..e8d0ed513e839 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/bundle_product_with_tier_price_selections_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\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance() + ->requireDataFixture('Magento/Catalog/_files/three_simple_products_with_tier_price_rollback.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +try { + $product = $productRepository->get('bundle_with_tier_price_selections', 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/simple_product_with_tier_prices_for_logged_in_group.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group.php new file mode 100644 index 0000000000000..35af54d574fd4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; +use Magento\Customer\Model\Group; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); + +$objectManager = Bootstrap::getObjectManager(); +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +$tpExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); +$product = $productRepository->get('simple', false, null, true); +$adminWebsite = $objectManager->get(WebsiteRepositoryInterface::class)->get('admin'); +$tierPriceExtensionAttributes = $tpExtensionAttributesFactory->create()->setWebsiteId($adminWebsite->getId()); +$pricesForCustomerGroupsInput = [ + [ + 'customer_group_id' => '1', + 'percentage_value'=> null, + 'qty'=> 1, + 'value'=> 20 + ], + [ + 'customer_group_id' => '1', + 'percentage_value'=> null, + 'qty'=> 2, + 'value'=> 30 + ] +]; +$productTierPrices = []; +foreach ($pricesForCustomerGroupsInput as $price) { + $productTierPrices[] = $tierPriceFactory->create( + [ + 'data' => $price + ] + )->setExtensionAttributes($tierPriceExtensionAttributes); +} +$product->setTierPrices($productTierPrices); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group_rollback.php new file mode 100644 index 0000000000000..328c1e229da5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group_rollback.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php new file mode 100644 index 0000000000000..cfb89b7de3305 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory; +use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; +use Magento\Customer\Model\Group; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); + +$objectManager = Bootstrap::getObjectManager(); +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +$tpExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); +$product = $productRepository->get('simple', false, null, true); +$adminWebsite = $objectManager->get(WebsiteRepositoryInterface::class)->get('admin'); +$tierPriceExtensionAttributes = $tpExtensionAttributesFactory->create()->setWebsiteId($adminWebsite->getId()); +$pricesForCustomerGroupsInput = [ + [ + 'customer_group_id' => Group::NOT_LOGGED_IN_ID, + 'percentage_value'=> null, + 'qty'=> 1, + 'value'=> 50 + ], + [ + 'customer_group_id' => Group::NOT_LOGGED_IN_ID, + 'percentage_value'=> null, + 'qty'=> 2, + 'value'=> 80 + ] +]; +$productTierPrices = []; +foreach ($pricesForCustomerGroupsInput as $price) { + $productTierPrices[] = $tierPriceFactory->create( + [ + 'data' => $price + ] + )->setExtensionAttributes($tierPriceExtensionAttributes); +} +$product->setTierPrices($productTierPrices); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group_rollback.php new file mode 100644 index 0000000000000..328c1e229da5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group_rollback.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price.php new file mode 100644 index 0000000000000..2b04935e46941 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price.php @@ -0,0 +1,68 @@ +<?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\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Customer\Model\Group; +use Magento\Store\Api\Data\WebsiteInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductTierPriceInterfaceFactory $tierPriceFactory */ +$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class); +/** @var ProductTierPriceExtensionFactory $tpExtensionAttributes */ +$tpExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class); + +/** @var WebsiteInterface $adminWebsite */ +$adminWebsite = $objectManager->get(WebsiteRepositoryInterface::class)->get('admin'); +$tierPriceExtensionAttributes = $tpExtensionAttributesFactory->create() + ->setWebsiteId($adminWebsite->getId()) + ->setPercentageValue(50); + +$tierPrice = $tierPriceFactory->create( + [ + 'data' => [ + 'customer_group_id' => Group::CUST_GROUP_ALL, + 'qty' => 2, + ], + ] +)->setExtensionAttributes($tierPriceExtensionAttributes); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productNumber = 1; +foreach ([10, 20, 30] as $price) { + /** @var $product Product */ + $product = $objectManager->create(Product::class); + $product->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([1]) + ->setName('Simple Product ' . $productNumber) + ->setSku('simple_' . $productNumber) + ->setPrice($price) + ->setWeight(1) + ->setTierPrices([$tierPrice]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + ); + + $productRepository->save($product); + $productNumber++; +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price_rollback.php new file mode 100644 index 0000000000000..9dbf7a38371b6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/three_simple_products_with_tier_price_rollback.php @@ -0,0 +1,31 @@ +<?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; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +foreach (['simple_1', 'simple_2', 'simple_3'] as $sku) { + try { + $product = $productRepository->get($sku, 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/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index dd36f90757398..4d844a7c6f229 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -108,6 +108,64 @@ public function testExport(): void $this->assertEquals(1, $occurrencesCount); } + /** + * Verify successful export of the product with custom attributes containing json and markup + * + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @magentoDbIsolation enabled + * @dataProvider exportWithJsonAndMarkupTextAttributeDataProvider + * @param string $attributeData + * @param string $expectedResult + * @return void + */ + public function testExportWithJsonAndMarkupTextAttribute(string $attributeData, string $expectedResult): void + { + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + $product = $productRepository->get('simple2'); + + /** @var \Magento\Eav\Model\Config $eavConfig */ + $eavConfig = $objectManager->get(\Magento\Eav\Model\Config::class); + $eavConfig->clear(); + $attribute = $eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'text_attribute'); + $attribute->setDefaultValue($attributeData); + /** @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository */ + $productAttributeRepository = $objectManager->get(\Magento\Catalog\Api\ProductAttributeRepositoryInterface::class); + $productAttributeRepository->save($attribute); + $product->setCustomAttribute('text_attribute', $attribute->getDefaultValue()); + $productRepository->save($product); + + $this->model->setWriter( + $this->objectManager->create( + \Magento\ImportExport\Model\Export\Adapter\Csv::class + ) + ); + $exportData = $this->model->export(); + $this->assertStringContainsString('Simple Product2', $exportData); + $this->assertStringContainsString($expectedResult, $exportData); + } + + /** + * @return array + */ + public function exportWithJsonAndMarkupTextAttributeDataProvider(): array + { + return [ + 'json' => [ + '{"type": "basic", "unit": "inch", "sign": "(\")", "size": "1.5\""}', + '"text_attribute={""type"": ""basic"", ""unit"": ""inch"", ""sign"": ""(\"")"", ""size"": ""1.5\""""}"' + ], + 'markup' => [ + '<div data-content>Element type is basic, measured in inches ' . + '(marked with sign (\")) with size 1.5\", mid-price range</div>', + '"text_attribute=<div data-content>Element type is basic, measured in inches ' . + '(marked with sign (\"")) with size 1.5\"", mid-price range</div>"' + ], + ]; + } + /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data_special_chars.php * @magentoDbIsolation enabled 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 3ca6754c77767..53e32483ee3d6 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -2344,6 +2344,67 @@ public function testProductWithWrappedAdditionalAttributes() ); } + /** + * @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @dataProvider importWithJsonAndMarkupTextAttributeDataProvider + * @param string $productSku + * @param string $expectedResult + * @return void + */ + public function testImportWithJsonAndMarkupTextAttribute(string $productSku, string $expectedResult): void + { + // added by _files/product_import_with_json_and_markup_attributes.csv + $this->importedProducts = [ + 'SkuProductWithJson', + 'SkuProductWithMarkup', + ]; + + $importParameters =[ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, + 'entity' => 'catalog_product', + \Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE => 0 + ]; + $filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class); + $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $source = $this->objectManager->create( + \Magento\ImportExport\Model\Import\Source\Csv::class, + [ + 'file' => __DIR__ . '/_files/products_to_import_with_json_and_markup_attributes.csv', + 'directory' => $directory + ] + ); + $this->_model->setParameters($importParameters); + $this->_model->setSource($source); + $errors = $this->_model->validateData(); + $this->assertTrue($errors->getErrorsCount() == 0); + $this->_model->importData(); + $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Api\ProductRepositoryInterface::class + ); + $product = $productRepository->get($productSku); + $this->assertEquals($expectedResult, $product->getData('text_attribute')); + } + + /** + * @return array + */ + public function importWithJsonAndMarkupTextAttributeDataProvider(): array + { + return [ + 'import of attribute with json' => [ + 'SkuProductWithJson', + '{"type": "basic", "unit": "inch", "sign": "(\")", "size": "1.5\""}' + ], + 'import of attribute with markup' => [ + 'SkuProductWithMarkup', + '<div data-content>Element type is basic, measured in inches ' . + '(marked with sign (\")) with size 1.5\", mid-price range</div>' + ], + ]; + } + /** * Import and check data from file. * @@ -3415,4 +3476,25 @@ public function importImagesDataProvider(): array ] ]; } + + /** + * Verify additional images url validation during import. + * + * @magentoDbIsolation enabled + * @return void + */ + public function testImportInvalidAdditionalImages(): void + { + $pathToFile = __DIR__ . '/_files/import_media_additional_images_with_wrong_url.csv'; + $filesystem = BootstrapHelper::getObjectManager()->create(Filesystem::class); + $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $source = $this->objectManager->create(Csv::class, ['file' => $pathToFile, 'directory' => $directory]); + $errors = $this->_model->setSource($source)->setParameters(['behavior' => Import::BEHAVIOR_APPEND]) + ->validateData(); + $this->assertEquals($errors->getErrorsCount(), 1); + $this->assertEquals( + "Wrong URL/path used for attribute additional_images", + $errors->getErrorByRowNumber(0)[0]->getErrorMessage() + ); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media.csv index a3e8f8e47ab08..3478512e25028 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media.csv @@ -1,2 +1,2 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus -simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, +simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg,magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_storeview.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_storeview.csv index ed8755a73fcb1..4d2e7234c9362 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_storeview.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_storeview.csv @@ -1,2 +1,2 @@ "sku","store_view_code","additional_images","additional_image_labels" -"simple","fixturestore","magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two" +"simple","fixturestore","magento_additional_image_one.jpg,magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two" diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_with_wrong_url.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_with_wrong_url.csv new file mode 100644 index 0000000000000..c2b9e4f6fa936 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_additional_images_with_wrong_url.csv @@ -0,0 +1,2 @@ +sku,product_type,name,price,attribute_set_code,additional_images +simple1,simple,"simple 1",25,Default,"additional_image_one.jpg,additional_image with spaces.jpg" diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_existing_images.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_existing_images.csv index a3e8f8e47ab08..3478512e25028 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_existing_images.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_existing_images.csv @@ -1,2 +1,2 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus -simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, +simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg,magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_hidden_images.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_hidden_images.csv index 1c1bebee57578..f54d4b7f401d4 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_hidden_images.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_hidden_images.csv @@ -1,2 +1,2 @@ -sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus -simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/2015 7:05,10/20/2015 7:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two","magento_image.jpg,magento_thumbnail.jpg,magento_additional_image_two.jpg",,,,,,, +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus +simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product,magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/2015 7:05,10/20/2015 7:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg,magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two","magento_image.jpg,magento_thumbnail.jpg,magento_additional_image_two.jpg",,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_json_and_markup_attributes.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_json_and_markup_attributes.csv new file mode 100644 index 0000000000000..e8372c19c8ff2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_json_and_markup_attributes.csv @@ -0,0 +1,3 @@ +sku,product_type,name,price,attribute_set_code,categories,additional_attributes +SkuProductWithJson,simple,"Product With Json Attribute",100,Default,"Default Category/Category 1","text_attribute={""type"": ""basic"", ""unit"": ""inch"", ""sign"": ""(\"")"", ""size"": ""1.5\""""}" +SkuProductWithMarkup,simple,"Product With Markup Attribute",100,Default,"Default Category/Category 1","text_attribute=<div data-content>Element type is basic, measured in inches (marked with sign (\"")) with size 1.5\"", mid-price range</div>" diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv index 8122433a8c9e1..6037ee008a8ec 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_non_existing_image.csv @@ -1,2 +1,2 @@ sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label1,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,associated_skus -simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,/no/exists/image/magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg, magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, +simple_new,,Default,simple,,base,New Product,,,,1,Taxable Goods,"Catalog, Search",10,,,,new-product,New Product,New Product,New Product ,/no/exists/image/magento_image.jpg,Image Label,magento_small_image.jpg,Small Image Label,magento_thumbnail.jpg,Thumbnail Label,magento_image.jpg,Image Label,10/20/15 07:05,10/20/15 07:05,,,Block after Info Column,,,,,,,,,,,,,"has_options=1,quantity_and_stock_status=In Stock,required_options=1",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,0,1,1,0,0,0,1,,,,"magento_additional_image_one.jpg,magento_additional_image_two.jpg","Additional Image Label One,Additional Image Label Two",,,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php new file mode 100644 index 0000000000000..2c31c9a8d688a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +/** + * Creates simple Catalog Rule with the following data: + * active, applied to all products, without time limits, with 25% off for all customer groups + */ +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\Rule; +use Magento\Customer\Model\GroupManagement; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var $banner Rule */ +$catalogRule = Bootstrap::getObjectManager()->create( + Rule::class +); + +$catalogRule + ->setIsActive(1) + ->setName('Test Catalog Rule With 25 Percent Off') + ->setCustomerGroupIds('0') + ->setDiscountAmount(25) + ->setWebsiteIds([0 => 1]) + ->setSimpleAction('by_percent') + ->setStopRulesProcessing(false) + ->setSortOrder(0) + ->setSubIsEnable(0) + ->setSubDiscountAmount(0) + ->save(); + +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = Bootstrap::getObjectManager() + ->get(IndexBuilder::class); +$indexBuilder->reindexFull(); +sleep(1); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all_rollback.php new file mode 100644 index 0000000000000..73e6bbff46648 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_25_customer_group_all_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; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var Rule $catalogRuleResource */ +$catalogRuleResource = $objectManager->create(Rule::class); +$connection = $catalogRuleResource->getConnection(); + +//Retrieve rule id by name +$select = $connection->select(); +$select->from($catalogRuleResource->getMainTable(), 'rule_id'); +$select->where('name = ?', 'Test Catalog Rule With 25 Percent Off'); +$ruleId = $connection->fetchOne($select); + +try { + /** @var CatalogRuleRepositoryInterface $ruleRepository */ + $ruleRepository = $objectManager->create(CatalogRuleRepositoryInterface::class); + $ruleRepository->deleteById($ruleId); +} catch (\Exception $ex) { + //Nothing to remove +} +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +$indexBuilder->reindexFull(); +sleep(1); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php new file mode 100644 index 0000000000000..d583dace85536 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +/** + * Creates simple Catalog Rule with the following data: + * active, applied to all products, without time limits, with 50% off for registered customer groups + */ +use Magento\CatalogRule\Model\Indexer\IndexBuilder; +use Magento\CatalogRule\Model\Rule; +use Magento\Customer\Model\GroupManagement; +use Magento\TestFramework\Helper\Bootstrap; + +/** @var $banner Rule */ +$catalogRule = Bootstrap::getObjectManager()->create( + Rule::class +); + +$catalogRule + ->setIsActive(1) + ->setName('Test Catalog Rule With 50 Percent Off') + ->setCustomerGroupIds('1') + ->setDiscountAmount(50) + ->setWebsiteIds([0 => 1]) + ->setSimpleAction('by_percent') + ->setStopRulesProcessing(false) + ->setSortOrder(0) + ->setSubIsEnable(0) + ->setSubDiscountAmount(0) + ->save(); + +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = Bootstrap::getObjectManager() + ->get(IndexBuilder::class); +$indexBuilder->reindexFull(); +sleep(1); diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group_rollback.php new file mode 100644 index 0000000000000..46df301157b5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group_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; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var Rule $catalogRuleResource */ +$catalogRuleResource = $objectManager->create(Rule::class); +$connection = $catalogRuleResource->getConnection(); + +//Retrieve rule id by name +$select = $connection->select(); +$select->from($catalogRuleResource->getMainTable(), 'rule_id'); +$select->where('name = ?', 'Test Catalog Rule With 50 Percent Off'); +$ruleId = $connection->fetchOne($select); + +try { + /** @var CatalogRuleRepositoryInterface $ruleRepository */ + $ruleRepository = $objectManager->create(CatalogRuleRepositoryInterface::class); + $ruleRepository->deleteById($ruleId); +} catch (\Exception $ex) { + //Nothing to remove +} +/** @var IndexBuilder $indexBuilder */ +$indexBuilder = $objectManager->get(IndexBuilder::class); +$indexBuilder->reindexFull(); +sleep(1); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Interception/PluginListGeneratorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Interception/PluginListGeneratorTest.php index 1046c678e253a..bda4cdd6cbaa5 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Interception/PluginListGeneratorTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Interception/PluginListGeneratorTest.php @@ -23,7 +23,14 @@ class PluginListGeneratorTest extends TestCase /** * Generated plugin list config for frontend scope */ - const CACHE_ID = 'primary|global|frontend|plugin-list'; + const CACHE_ID_FRONTEND = 'primary|global|frontend|plugin-list'; + + /** + * Generated plugin list config for dummy scope + */ + const CACHE_ID_DUMMY = 'primary|global|dummy|plugin-list'; + + private $cacheIds = [self::CACHE_ID_FRONTEND, self::CACHE_ID_DUMMY]; /** * @var PluginListGenerator @@ -90,31 +97,51 @@ protected function setUp(): void */ public function testPluginListConfigGeneration() { - $scopes = ['frontend']; + $scopes = ['global', 'frontend', 'dummy']; + $globalPlugin = 'genericHeaderPlugin'; + $frontendPlugin = 'response-http-page-cache'; $this->model->write($scopes); - $configData = $this->model->load(self::CACHE_ID); - $this->assertNotEmpty($configData[0]); - $this->assertNotEmpty($configData[1]); - $this->assertNotEmpty($configData[2]); - $expected = [ + $configDataFrontend = $this->model->load(self::CACHE_ID_FRONTEND); + $this->assertNotEmpty($configDataFrontend[0]); + $this->assertNotEmpty($configDataFrontend[1]); + $this->assertNotEmpty($configDataFrontend[2]); + $expectedFrontend = [ 1 => [ - 0 => 'genericHeaderPlugin', - 1 => 'response-http-page-cache' + 0 => $globalPlugin, + 1 => $frontendPlugin ] ]; // Here in test is assumed that this class below has 3 plugins. But the amount of plugins and class itself // may vary. If it is changed, please update these assertions. $this->assertArrayHasKey( 'Magento\\Framework\\App\\Response\\Http_sendResponse___self', - $configData[2], + $configDataFrontend[2], 'Processed plugin does not exist in the processed plugins array.' ); $this->assertSame( - $expected, - $configData[2]['Magento\\Framework\\App\\Response\\Http_sendResponse___self'], + $expectedFrontend, + $configDataFrontend[2]['Magento\\Framework\\App\\Response\\Http_sendResponse___self'], 'Plugin configurations are not equal' ); + + $configDataDummy = $this->model->load(self::CACHE_ID_DUMMY); + /** + * Make sure "dummy" scope with no plugins in system should not contain plugins from "frontend" scope + */ + $this->assertNotContains( + $frontendPlugin, + $configDataDummy[2]['Magento\\Framework\\App\\Response\\Http_sendResponse___self'][1], + 'Plugin configurations are not equal. "dummy" scope should not contain plugins from "frontend" scope' + ); + /** + * Make sure "dummy" scope with no plugins in system should contain plugins from "global" scope + */ + $this->assertContains( + $globalPlugin, + $configDataDummy[2]['Magento\\Framework\\App\\Response\\Http_sendResponse___self'][1], + 'Plugin configurations are not equal. "dummy" scope should contain plugins from "global" scope' + ); } /** @@ -137,11 +164,13 @@ private function getCustomDirs(): array */ protected function tearDown(): void { - $filePath = $this->directoryList->getPath(DirectoryList::GENERATED_METADATA) - . '/' . self::CACHE_ID . '.' . 'php'; + foreach ($this->cacheIds as $cacheId) { + $filePath = $this->directoryList->getPath(DirectoryList::GENERATED_METADATA) + . '/' . $cacheId . '.' . 'php'; - if (file_exists($filePath)) { - $this->file->deleteFile($filePath); + if (file_exists($filePath)) { + $this->file->deleteFile($filePath); + } } } } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Controller/Hostedpro/ReturnActionTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Hostedpro/ReturnActionTest.php new file mode 100644 index 0000000000000..b3870c69b23f0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/Controller/Hostedpro/ReturnActionTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Paypal\Controller\Hostedpro; + +use Magento\TestFramework\TestCase\AbstractController; +use Laminas\Stdlib\Parameters; + +/** + * Tests PayPal HostedPro return controller. + */ +class ReturnActionTest extends AbstractController +{ + /** + * Tests customer redirect on success page after return from PayPal HostedPro payment. + * + * @SuppressWarnings(PHPMD.Superglobals) + */ + public function testReturnRedirect() + { + $redirectUri = 'paypal/hostedpro/return'; + $this->setRequestUri($redirectUri); + $this->getRequest()->setMethod('POST'); + + $this->dispatch($redirectUri); + $this->assertRedirect($this->stringContains('checkout/onepage/success')); + + $this->assertEmpty( + $_SESSION, + 'Session start has to be skipped for current controller' + ); + } + + /** + * Sets REQUEST_URI into request object. + * + * @param string $requestUri + * @return void + */ + private function setRequestUri(string $requestUri) + { + $request = $this->getRequest(); + $reflection = new \ReflectionClass($request); + $property = $reflection->getProperty('requestUri'); + $property->setAccessible(true); + $property->setValue($request, null); + + $request->setServer(new Parameters(['REQUEST_URI' => $requestUri])); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Review/Block/ViewTest.php b/dev/tests/integration/testsuite/Magento/Review/Block/ViewTest.php new file mode 100644 index 0000000000000..74bb31d7cb48d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Review/Block/ViewTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Review\Block; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\Customer\Model\Session; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Registry; +use Magento\Framework\View\LayoutInterface; +use Magento\Review\Model\ResourceModel\Review\Product\CollectionFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Test for displaying product review block. + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + */ +class ViewTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Session */ + private $customerSession; + + /** @var CollectionFactory */ + private $collectionFactory; + + /** @var Registry */ + private $registry; + + /** @var View */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->customerSession = $this->objectManager->get(Session::class); + $this->collectionFactory = $this->objectManager->get(CollectionFactory::class); + $this->registry = $this->objectManager->get(Registry::class); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(View::class); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + $this->registry->unregister('current_review'); + $this->registry->unregister('current_product'); + $this->registry->unregister('product'); + $this->customerSession->setCustomerId(null); + + parent::tearDown(); + } + + /** + * Test product review block + * + * @magentoDataFixture Magento/Review/_files/product_review_with_rating.php + * + * @return void + * @throws NoSuchEntityException + */ + public function testProductReviewBlock(): void + { + $this->customerSession->setCustomerId(1); + $review = $this->collectionFactory->create()->addCustomerFilter(1)->getFirstItem(); + $this->registerReview($review); + $this->assertNotNull($review->getReviewId()); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product = $productRepository->get('simple', false, null, true); + $this->registerProduct($product); + + $blockHtml = $this->block->setReviewId($review->getReviewId())->toHtml(); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf("//div[contains(@class, 'details')]/h3[contains(text(), '%s')]", $review->getName()), + $blockHtml + ), + 'Product name wasn\'t found.' + ); + $ratings = $this->block->getRating(); + $this->assertCount(2, $ratings); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + sprintf( + "//a[contains(@class, 'action back')]/span[contains(text(), '%s')]", + __('Back to Product Reviews') + ), + $blockHtml + ), + sprintf('%s button wasn\'t found.', __('Back to Product Reviews')) + ); + } + + /** + * Register the product + * + * @param ProductInterface $product + * @return void + */ + private function registerProduct(ProductInterface $product): void + { + $this->registry->unregister('current_product'); + $this->registry->unregister('product'); + $this->registry->register('current_product', $product); + $this->registry->register('product', $product); + } + + /** + * Register the current review + * + * @param Product $review + * @return void + */ + private function registerReview(Product $review): void + { + $this->registry->unregister('current_review'); + $this->registry->register('current_review', $review); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating.php b/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating.php new file mode 100644 index 0000000000000..47a402ae44fc4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Backend\App\Area\FrontNameResolver; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Framework\Registry; +use Magento\Review\Model\Rating; +use Magento\Review\Model\Rating\Option; +use Magento\Review\Model\ResourceModel\Review\Collection; +use Magento\Review\Model\Review; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Bootstrap::getInstance()->loadArea( + FrontNameResolver::AREA_CODE +); +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var CustomerRegistry $customerRegistry */ +$customerRegistry = $objectManager->create(CustomerRegistry::class); +$customer = $customerRegistry->retrieve(1); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +$product = $productRepository->get('simple'); +$storeId = $objectManager->get( + StoreManagerInterface::class +)->getStore()->getId(); + +$review = $objectManager->create( + Review::class, + ['data' => [ + 'customer_id' => $customer->getId(), + 'title' => 'Review Summary', + 'detail' => 'Review text', + 'nickname' => 'Nickname', + ]] +); + +$review + ->setEntityId($review->getEntityIdByCode(Review::ENTITY_PRODUCT_CODE)) + ->setEntityPkValue($product->getId()) + ->setStatusId(Review::STATUS_APPROVED) + ->setStoreId($storeId) + ->setStores([$storeId]) + ->save(); + +$objectManager->get(Registry::class)->register( + 'review_data', + $review +); + +/** @var Collection $ratingCollection */ +$ratingCollection = $objectManager->create( + Rating::class +)->getCollection() + ->setPageSize(2) + ->setCurPage(1); + +foreach ($ratingCollection as $rating) { + $rating->setStores([$storeId])->setIsActive(1)->save(); +} + +foreach ($ratingCollection as $rating) { + $ratingOption = $objectManager + ->create(Option::class) + ->getCollection() + ->setPageSize(1) + ->setCurPage(2) + ->addRatingFilter($rating->getId()) + ->getFirstItem(); + $rating->setReviewId($review->getId()) + ->addOptionVote($ratingOption->getId(), $product->getId()); +} + +$objectManager->get(Registry::class)->register( + 'rating_data', + $ratingCollection->getFirstItem() +); diff --git a/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating_rollback.php b/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating_rollback.php new file mode 100644 index 0000000000000..0931d881a6fdc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Review/_files/product_review_with_rating_rollback.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Order/PrintOrder/LogoTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/PrintOrder/LogoTest.php new file mode 100644 index 0000000000000..aadd3ab7b956e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Order/PrintOrder/LogoTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Block\Order\PrintOrder; + +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\App\State; +use Magento\Theme\Block\Html\Header\Logo; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\ObjectManagerInterface; +use Magento\Theme\ViewModel\Block\Html\Header\LogoPathResolver as LogoPathResolverDefault; +use Magento\Sales\ViewModel\Header\LogoPathResolver as LogoPathResolverSales; +use \PHPUnit\Framework\TestCase; + +class LogoTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var WriteInterface + */ + private $mediaDirectory; + + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $filesystem = $this->objectManager->get(Filesystem::class); + $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $this->objectManager->get(State::class) + ->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND); + Bootstrap::getInstance() + ->loadArea(\Magento\Framework\App\Area::AREA_FRONTEND); + } + + /** + * @magentoConfigFixture default_store design/header/logo_src default/logo.jpg + * @magentoConfigFixture default_store sales/identity/logo_html default/logo_sales.jpg + * @throws \Magento\Framework\Exception\FileSystemException + */ + public function testGetLogoSrc(): void + { + $host = 'http://localhost/media/'; + $defaultLogoFile= 'logo.jpg'; + $defaultPath = 'logo/default/' . $defaultLogoFile; + $salesLogoFile = 'logo_sales.jpg'; + $salesPath = 'sales/store/logo_html/default/' . $salesLogoFile; + $this->mediaDirectory->writeFile($defaultPath, ''); + $this->mediaDirectory->writeFile($salesPath, ''); + $blockArguments = ['data' => + ['logoPathResolver' => $this->objectManager->get(LogoPathResolverDefault::class)] + ]; + /** @var Logo $block */ + $block = $this->objectManager->create(LayoutInterface::class) + ->createBlock(Logo::class, 'logo', $blockArguments); + $this->assertSame($host . $defaultPath, $block->getLogoSrc()); + $blockArguments = ['data' => + ['logoPathResolver' => $this->objectManager->get(LogoPathResolverSales::class)] + ]; + /** @var Logo $block */ + $block = $this->objectManager->create(LayoutInterface::class) + ->createBlock(Logo::class, 'logo', $blockArguments); + $this->assertSame($host . $salesPath, $block->getLogoSrc()); + $this->mediaDirectory->delete($defaultPath); + $this->mediaDirectory->delete($salesPath); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php index d07ec84b6eddc..b1c7843dfad32 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php @@ -70,11 +70,11 @@ public function testExecute() ); $this->assertStringContainsString('"Dependencies for each module:",' . PHP_EOL, $fileContents); $this->assertStringContainsString( - '"Magento\A",1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL, + 'Magento\A,1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL, $fileContents ); $this->assertStringContainsString( - '"Magento\B",1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL, + 'Magento\B,1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL, $fileContents ); } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Module/Dependency/_files/expected/framework-dependencies.csv b/dev/tests/integration/testsuite/Magento/Setup/Module/Dependency/_files/expected/framework-dependencies.csv index e1c5732b94dcb..9f358f3fa7a25 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Module/Dependency/_files/expected/framework-dependencies.csv +++ b/dev/tests/integration/testsuite/Magento/Setup/Module/Dependency/_files/expected/framework-dependencies.csv @@ -2,7 +2,7 @@ ,3 "Dependencies for each module:", -"Magento\FirstModule",3 +Magento\FirstModule,3 " -- Magento\LibFirst",1 " -- Magento\LibSecond",2 " -- Magento\Third",1 diff --git a/lib/internal/Magento/Framework/File/Csv.php b/lib/internal/Magento/Framework/File/Csv.php index 1b1decdb5327c..e33b38562bf57 100644 --- a/lib/internal/Magento/Framework/File/Csv.php +++ b/lib/internal/Magento/Framework/File/Csv.php @@ -30,6 +30,11 @@ class Csv */ protected $_enclosure = '"'; + /** + * @var string + */ + private $escape = "\0"; + /** * @var File */ @@ -96,7 +101,7 @@ public function getData($file) } $fh = fopen($file, 'r'); - while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure)) { + while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure, $this->escape)) { $data[] = $rowData; } fclose($fh); diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index bc08f67228849..7b508942c107d 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -647,7 +647,7 @@ public function fileRead($resource, $length) * @return array|bool|null * @throws FileSystemException */ - public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') + public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0") { $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape); if ($result === null) { @@ -801,7 +801,10 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure } } - $result = @fputcsv($resource, $data, $delimiter, $enclosure); + // Escape symbol is needed to fix known issue in PHP broken fputcsv escaping functionality + // where backslash followed by double quote breaks file consistency + $escape = "\0"; + $result = @fputcsv($resource, $data, $delimiter, $enclosure, $escape); if (!$result) { throw new FileSystemException( new Phrase( diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php index beeb1e928262c..9f69a38527ab3 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php @@ -642,7 +642,7 @@ public function fileRead($resource, $length) * @return array|bool|null * @throws FileSystemException */ - public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') + public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0") { $result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape); if ($result === null) { diff --git a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php index afea4d3bc7b07..706077522c675 100644 --- a/lib/internal/Magento/Framework/Filesystem/DriverInterface.php +++ b/lib/internal/Magento/Framework/Filesystem/DriverInterface.php @@ -276,7 +276,7 @@ public function fileRead($resource, $length); * @return array|bool|null * @throws FileSystemException */ - public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\'); + public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0"); /** * Returns position of read/write pointer diff --git a/lib/internal/Magento/Framework/Filesystem/File/Read.php b/lib/internal/Magento/Framework/Filesystem/File/Read.php index f48e50b7d693d..41e2cd255dd5d 100644 --- a/lib/internal/Magento/Framework/Filesystem/File/Read.php +++ b/lib/internal/Magento/Framework/Filesystem/File/Read.php @@ -124,7 +124,7 @@ public function readLine($length, $ending = null) * @param string $escape [optional] * @return array|bool|null */ - public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') + public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0") { return $this->driver->fileGetCsv($this->resource, $length, $delimiter, $enclosure, $escape); } diff --git a/lib/internal/Magento/Framework/Filesystem/File/ReadInterface.php b/lib/internal/Magento/Framework/Filesystem/File/ReadInterface.php index e27086709d8b1..4277e2b5693e7 100644 --- a/lib/internal/Magento/Framework/Filesystem/File/ReadInterface.php +++ b/lib/internal/Magento/Framework/Filesystem/File/ReadInterface.php @@ -46,7 +46,7 @@ public function readLine($length, $ending = null); * @param string $escape [optional] * @return array|bool false on end of file */ - public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\'); + public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0"); /** * Returns the current position diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index effc291bb883b..8f3a03dd4fc20 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -227,8 +227,6 @@ public function loadScopedVirtualTypes($scopePriorityScheme, $loadedScopes, $plu $data = $this->reader->read($scopeCode) ?: []; unset($data['preferences']); if (count($data) > 0) { - $inherited = []; - $processed = []; $pluginData = $this->merge($data, $pluginData); foreach ($data as $class => $config) { if (isset($config['type'])) { @@ -236,6 +234,8 @@ public function loadScopedVirtualTypes($scopePriorityScheme, $loadedScopes, $plu } } } + $inherited = []; + $processed = []; $loadedScopes[$scopeCode] = true; } if ($this->isCurrentScope($scopeCode)) { diff --git a/pub/media/customer_address/.htaccess b/pub/media/customer_address/.htaccess new file mode 100644 index 0000000000000..b97408bad3f2e --- /dev/null +++ b/pub/media/customer_address/.htaccess @@ -0,0 +1,7 @@ +<IfVersion < 2.4> + order allow,deny + deny from all +</IfVersion> +<IfVersion >= 2.4> + Require all denied +</IfVersion> From fd4a421c4aaff7e2fcc15778f51e309531a8ef52 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 4 Jan 2021 12:30:06 +0200 Subject: [PATCH 118/242] MC-39636: Create automated test for: "Try to save the category without filling the required fields." --- .../Category/Save/SaveCategoryTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php index dc74a2c2cba7b..a64e8b769cf23 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php @@ -11,7 +11,9 @@ use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Model\Category; use Magento\Cms\Api\GetBlockByIdentifierInterface; +use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Message\MessageInterface; use Magento\Store\Model\StoreManagerInterface; /** @@ -87,4 +89,21 @@ public function testCreateCategoryWithCmsBlock(): void $category = $this->categoryRepository->get($this->createdCategoryId); $this->assertEquals($blockId, $category->getLandingPage()); } + + /** + * @return void + */ + public function testTryToCreateCategoryWithEmptyValues(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue([ + CategoryInterface::KEY_NAME => 'test', + CategoryInterface::KEY_IS_ACTIVE => 1, + 'use_config' => [], + 'return_session_messages_only' => false, + ]); + $this->dispatch('backend/catalog/category/save'); + $message = 'The "Available Product Listing Sort By" attribute is required. Enter and try again.'; + $this->assertSessionMessages($this->equalTo([(string)__($message)]), MessageInterface::TYPE_ERROR); + } } From e403ec5286056765da613980b48babadc1a2ffe4 Mon Sep 17 00:00:00 2001 From: Anna Pak <58164147+AnnaAPak@users.noreply.github.com> Date: Mon, 4 Jan 2021 12:42:02 +0200 Subject: [PATCH 119/242] Refactored with updated Action Group name Co-authored-by: Eduard Chitoraga <e.chitoraga@atwix.com> --- .../Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml | 2 +- .../Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml | 2 +- .../Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml | 2 +- .../Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml | 2 +- .../Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml | 2 +- .../Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml | 2 +- .../Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml | 2 +- .../Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml | 2 +- .../Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml | 2 +- .../Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml | 2 +- .../AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml | 2 +- ...NewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml | 2 +- .../AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml | 2 +- .../Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml | 2 +- .../Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml | 4 ++-- .../Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml | 4 ++-- .../Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml | 4 ++-- .../Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml | 2 +- .../Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml | 4 ++-- .../Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml | 4 ++-- .../Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml | 4 ++-- 26 files changed, 37 insertions(+), 37 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml index fd9e210021996..b5ae4d1eca59a 100644 --- a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.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="AdminClearFiltersOnGridActionGroup"> + <actionGroup name="AdminClearGridFiltersActionGroup"> <annotations> <description>Click the Clear filters on the grid.</description> </annotations> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml index 08c3ba49d0649..92fd18cc24c31 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithNoRedirectTest.xml @@ -79,7 +79,7 @@ <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updatedurl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's old URL path doesn't show redirect path--> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickOnResetButton1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickOnResetButton1"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoad3"/> <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml index 49d2c24f26bae..f88636fa767e8 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateTopCategoryUrlWithRedirectTest.xml @@ -77,7 +77,7 @@ <see selector="{{AdminUrlRewriteIndexSection.gridCellByColumnRowNumber('1', 'Request Path')}}" userInput="$$createDefaultCategory.name$$/$$createTwoLevelNestedCategories.name$$/updateredirecturl.html" stepKey="seeTheRedirectPath"/> <!-- Verify third level category's Redirect path, Target Path and Redirect type for old URL --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickOnResetButton1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickOnResetButton1"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoad4"/> <click selector="{{AdminDataGridHeaderSection.filters}}" stepKey="openUrlRewriteGridFilters1"/> <fillField selector="{{AdminDataGridHeaderSection.filterFieldInput('request_path')}}" userInput="$$createThreeLevelNestedCategories.name$$" stepKey="fillOldUrlInRedirectPathFilter"/> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml index 16ddacf0e04ed..8cf6320736bb4 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewTest.xml @@ -29,7 +29,7 @@ <after> <!--Delete created Template--> <actionGroup ref="DeleteEmailTemplateActionGroup" stepKey="deleteTemplate"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clearFilters"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clearFilters"/> <!--Logout from Admin Area--> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml index 06da55e2cac49..e1632c98a1cf0 100644 --- a/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml +++ b/app/code/Magento/Email/Test/Mftf/Test/AdminEmailTemplatePreviewWithDirectivesTest.xml @@ -29,7 +29,7 @@ <after> <!--Delete created Template--> <actionGroup ref="DeleteEmailTemplateActionGroup" stepKey="deleteTemplate"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clearFilters"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clearFilters"/> <!--Logout from Admin Area--> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/> </after> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml index 62d32fba70496..2f418dddf3884 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateDefaultsTaxRuleTest.xml @@ -42,7 +42,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="assertTaxRuleSuccessMessage" /> <!-- Verify we see created tax rule with defaults(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch" /> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml index 3cbd47d4f3a0f..7fa1daeb063ca 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateAllPostCodesTest.xml @@ -43,7 +43,7 @@ <!-- Verify the tax rate grid page shows the tax rate we just created --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillNameFilter"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="Australia" stepKey="fillCountryFilter"/> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="*" stepKey="fillPostCodeFilter"/> @@ -54,7 +54,7 @@ <!-- Go to the tax rate edit page for our new tax rate --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex3"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillNameFilter2"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml index 2fb3a4cb9935c..e189e45483197 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateLargeRateTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for large postcodes and verify we see expected values on the tax rate grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="France" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="*" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml index 3193ed5bb7391..9a5566c2db881 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateSpecificPostcodeTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Verify the tax rate grid page shows the specific postcode we just created --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="Canada" stepKey="fillCountryFilter"/> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="180" stepKey="fillPostCodeFilter"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml index 3b2c9f0a58fa5..48217628b927a 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateWiderZipCodeRangeTest.xml @@ -45,7 +45,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for zipCodeRange and verify we see expected values on the tax rate grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="United Kingdom" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="1-7800935" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml index 827b2fcbac2b3..d237e52a60472 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRateZipCodeRangeTest.xml @@ -46,7 +46,7 @@ <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> <!-- Create a tax rate for zipCodeRange and verify we see expected values on the tax rate grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{SimpleTaxRate.code}}" stepKey="fillTaxIdentifierField2"/> <selectOption selector="{{AdminTaxRateGridSection.filterByCountry}}" userInput="United States" stepKey="selectCountry2" /> <fillField selector="{{AdminTaxRateGridSection.filterByPostCode}}" userInput="90001-96162" stepKey="seeTaxPostCode1"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml index 160f9c008a5d2..5ae2742ad21fb 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithCustomerAndProductTaxClassTest.xml @@ -68,7 +68,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with customer and product class(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml index 9dabe5a317644..21f8b844adb58 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewAndExistingTaxRateAndCustomerAndProductTaxClassTest.xml @@ -63,7 +63,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with new and existing tax rate, customer tax class, product tax class(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml index 38bef10da1af2..25b919722ced9 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithNewTaxClassesAndTaxRateTest.xml @@ -67,7 +67,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with new tax classes and tax rate(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml index 5dd233a66d228..7ba6caf5402b1 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminCreateTaxRuleWithZipRangeTest.xml @@ -65,7 +65,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see created tax rule with zip range(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml index 95572488819ff..2fde2e2cd02d0 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminDeleteTaxRuleTest.xml @@ -31,7 +31,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -46,7 +46,7 @@ <!-- Confirm Deleted Tax Rule(from the above step) on the tax rule grid page --> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <see selector="{{AdminTaxRuleGridSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeAssertTaxRuleNotFound"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml index ff45a8f324326..addd8d2832417 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateDefaultTaxRuleTest.xml @@ -39,7 +39,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -64,7 +64,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with default(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml index 8a14a84741faf..65945f80048ad 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithCustomClassesTest.xml @@ -40,7 +40,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -62,7 +62,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with default(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml index 94672b35c5aba..c208912654fdb 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminUpdateTaxRuleWithFixedZipUtahTest.xml @@ -44,7 +44,7 @@ </after> <actionGroup ref="AdminTaxRuleGridOpenPageActionGroup" stepKey="goToTaxRuleIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="$$initialTaxRule.code$$" stepKey="fillTaxCodeSearch"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRuleGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -66,7 +66,7 @@ <see selector="{{AdminTaxRuleGridSection.successMessage}}" userInput="You saved the tax rule." stepKey="seeAssertTaxRuleSuccessMessage"/> <!-- Verify we see updated tax rule with fixed zip Utah(from the above step) on the tax rule grid page --> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRuleGridSection.code}}" userInput="{{SimpleTaxRule.code}}" stepKey="fillTaxRuleCode2"/> <click selector="{{AdminTaxRuleGridSection.search}}" stepKey="clickSearch2"/> <waitForPageLoad stepKey="waitForTaxRuleSearch"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml index c9f38a38b81e8..3abdb45faf95a 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/DeleteTaxRateEntityTest.xml @@ -36,7 +36,7 @@ <!-- Confirm Deleted TaxIdentifier(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRate.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <see selector="{{AdminTaxRateGridSection.emptyText}}" userInput="We couldn't find any records." stepKey="seeSuccess"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml index 549b7d01375c2..b102b4d945019 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update01TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -45,7 +45,7 @@ <!-- Verify we see updated 0.1 tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateFrance.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml index b1f7611bd36ea..115a1df4631e5 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update100TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -44,7 +44,7 @@ <!-- Verify we see updated TaxIdentifier(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateUS.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml index 343d912941e6c..5594cf58e7b21 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/Update1299TaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax identifier on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode1"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -45,7 +45,7 @@ <!-- Verify we see updated tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateUK.code}}" stepKey="fillTaxIdentifierField2"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml index 4ccc77c940438..da531ea373aa1 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateAnyRegionTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -44,7 +44,7 @@ <!-- Verify we see updated any region tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{taxRateCustomRateCanada.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml index 00ac9e045a5ad..717d9b9428267 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateDecimalTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -46,7 +46,7 @@ <!-- Verify we see updated tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex2"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRateWithZipRange.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> diff --git a/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml index 79a5b4349f69d..b664d334162ed 100644 --- a/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml +++ b/app/code/Magento/Tax/Test/Mftf/Test/UpdateLargeTaxRateEntityTest.xml @@ -28,7 +28,7 @@ <!-- Search the tax rate on tax grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex1"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters1"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters1"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="$$initialTaxRate.code$$" stepKey="fillCode"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch1"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow1"/> @@ -43,7 +43,7 @@ <!-- Verify we see updated large tax rate(from the above step) on the tax rate grid page --> <actionGroup ref="AdminTaxRateGridOpenPageActionGroup" stepKey="goToTaxRateIndex4"/> - <actionGroup ref="AdminClearFiltersOnGridActionGroup" stepKey="clickClearFilters2"/> + <actionGroup ref="AdminClearGridFiltersActionGroup" stepKey="clickClearFilters2"/> <fillField selector="{{AdminTaxRateGridSection.filterByTaxIdentifier}}" userInput="{{defaultTaxRateWithLargeRate.code}}" stepKey="fillTaxIdentifierField3"/> <click selector="{{AdminTaxRateGridSection.search}}" stepKey="clickSearch2"/> <click selector="{{AdminTaxRateGridSection.nthRow('1')}}" stepKey="clickFirstRow2"/> From 2af6793227406b4c66a4a829fbd468489149a977 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Mon, 4 Jan 2021 12:47:39 +0200 Subject: [PATCH 120/242] renamed Action Group --- ...OnGridActionGroup.xml => AdminClearGridFiltersActionGroup.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/code/Magento/Backend/Test/Mftf/ActionGroup/{AdminClearFiltersOnGridActionGroup.xml => AdminClearGridFiltersActionGroup.xml} (100%) diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearGridFiltersActionGroup.xml similarity index 100% rename from app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearFiltersOnGridActionGroup.xml rename to app/code/Magento/Backend/Test/Mftf/ActionGroup/AdminClearGridFiltersActionGroup.xml From aec946d2074ee3ba7865c89c7776ccca6d430f29 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Mon, 4 Jan 2021 15:38:44 +0200 Subject: [PATCH 121/242] MC-39140: Error when adding products widget to CMS page in the admin --- .../ResourceModel/Product/Collection.php | 7 ++- .../ResourceModel/Product/CollectionTest.php | 50 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 3f908663c8e5e..a247e6b09760b 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -916,7 +916,12 @@ public function addWebsiteFilter($websites = null) } $this->_productLimitationFilters['website_ids'] = $websites; - $this->_applyProductLimitations(); + + if ($this->getStoreId() == Store::DEFAULT_STORE_ID) { + $this->_productLimitationJoinWebsite(); + } else { + $this->_applyProductLimitations(); + } return $this; } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php index 2bf504369b8a7..9a55e48cfb1b4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php @@ -38,6 +38,7 @@ use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\Validator\UniversalFactory; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -93,6 +94,11 @@ class CollectionTest extends TestCase */ private $storeManager; + /** + * @var ProductLimitation|MockObject + */ + private $productLimitationMock; + /** * @var EntityFactory|MockObject */ @@ -192,7 +198,7 @@ protected function setUp(): void $this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0); $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $productLimitationMock = $this->createMock( + $this->productLimitationMock = $this->createMock( ProductLimitation::class ); $productLimitationFactoryMock = $this->getMockBuilder( @@ -201,7 +207,7 @@ protected function setUp(): void ->setMethods(['create'])->getMock(); $productLimitationFactoryMock->method('create') - ->willReturn($productLimitationMock); + ->willReturn($this->productLimitationMock); $this->collection = $this->objectManager->getObject( Collection::class, [ @@ -432,4 +438,44 @@ public function testGetNewEmptyItem() $secondItem = $this->collection->getNewEmptyItem(); $this->assertEquals($firstItem, $secondItem); } + + /** + * Test to add website filter in admin area + */ + public function testAddWebsiteFilterOnAdminStore(): void + { + $websiteIds = [2]; + $websiteTable = 'catalog_product_website'; + $joinCondition = 'join condition'; + $this->productLimitationMock->expects($this->atLeastOnce()) + ->method('offsetSet') + ->with('website_ids', $websiteIds); + $this->productLimitationMock->method('offsetExists') + ->with('website_ids') + ->willReturn(true); + $this->productLimitationMock->method('offsetGet') + ->with('website_ids') + ->willReturn($websiteIds); + $this->connectionMock->expects($this->once()) + ->method('quoteInto') + ->with('product_website.website_id IN(?)', $websiteIds, 'int') + ->willReturn($joinCondition); + $this->selectMock->method('getPart')->with(Select::FROM)->willReturn([]); + /** @var AbstractEntity|MockObject $eavEntity */ + $eavEntity = $this->createMock(AbstractEntity::class); + $eavEntity->method('getTable') + ->with('catalog_product_website') + ->willReturn($websiteTable); + $this->selectMock->expects($this->once()) + ->method('join') + ->with( + ['product_website' => $websiteTable], + 'product_website.product_id = e.entity_id AND ' . $joinCondition, + [] + ); + + $this->collection->setEntity($eavEntity); + $this->collection->setStoreId(Store::DEFAULT_STORE_ID); + $this->collection->addWebsiteFilter($websiteIds); + } } From 245fc040700e534181cff1956688c77c17eb33d1 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 4 Jan 2021 17:06:37 +0200 Subject: [PATCH 122/242] MC-40061: Create automated test for: "Subscribe to stock price alert" --- .../Product/Edit/Tab/Alerts/StockTest.php | 90 +++++++++++++++++++ .../Product/Form/Modifier/AlertsTest.php | 56 ++++++++++++ .../_files/product_alert_rollback.php | 33 +++++++ .../_files/stock_alert_on_second_website.php | 66 ++++++++++++++ ...stock_alert_on_second_website_rollback.php | 52 +++++++++++ 5 files changed, 297 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php new file mode 100644 index 0000000000000..d03bc935bcd72 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Check stock alert grid + * + * @see \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts\Stock + * + * @magentoAppArea adminhtml + */ +class StockTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Stock */ + private $block; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Stock::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @dataProvider alertsDataProvider + * + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/ProductAlert/_files/product_alert.php + * @magentoDataFixture Magento/ProductAlert/_files/stock_alert_on_second_website.php + * + * @param string $sku + * @param string $expectedEmail + * @param string|null $storeCode + * @return void + */ + public function testGridCollectionWIthStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void + { + $productId = (int)$this->productRepository->get($sku)->getId(); + $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : null; + $this->block->getRequest()->setParams(['id' => $productId, 'store' => $storeId]); + $collection = $this->block->getPreparedCollection(); + $this->assertCount(1, $collection); + $this->assertEquals($expectedEmail, $collection->getFirstItem()->getEmail()); + } + + /** + * @return array + */ + public function alertsDataProvider(): array + { + return [ + 'without_store_id_filter' => [ + 'product_sku' => 'simple', + 'expected_customer_emails' => 'customer@example.com', + ], + 'with_store_id_filter' => [ + 'product_sku' => 'simple_on_second_website', + 'expected_customer_emails' => 'customer_second_ws_with_addr@example.com', + 'store_code' => 'fixture_third_store', + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php new file mode 100644 index 0000000000000..96ddc66c875b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; + +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Alerts modifier test + * + * @see \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Alerts + * + * @magentoAppArea adminhtml + */ +class AlertsTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Alerts */ + private $stockAlertsModifier; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->stockAlertsModifier = $this->objectManager->get(Alerts::class); + } + + /** + * @magentoConfigFixture current_store catalog/productalert/allow_stock 1 + * + * @return void + */ + public function testModifyMeta(): void + { + $meta = $this->stockAlertsModifier->modifyMeta([]); + $this->assertArrayHasKey('alerts', $meta); + $content = $meta['alerts']['children'][Alerts::DATA_SCOPE_STOCK]['arguments']['data']['config']['content']; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath("//div[@data-grid-id='alertStock']", $content) + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php new file mode 100644 index 0000000000000..e9c4900ded341 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_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\Registry; +use Magento\ProductAlert\Model\StockFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +$objectManager = Bootstrap::getObjectManager(); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer@example.com'); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$stockAlert = $stockFactory->create(); +$stockAlert->deleteCustomer((int)$customer->getId()); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php new file mode 100644 index 0000000000000..b9d4c4b81f69b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\ProductAlert\Model\ResourceModel\Stock as StockResource; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var StockResource $stockResource */ +$stockResource = $objectManager->get(StockResource::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); + + +$product = $productFactory->create(); +$product + ->setTypeId('simple') + ->setAttributeSetId(4) + ->setWebsiteIds([(int)$secondWebsite->getId()]) + ->setName('Simple Product2') + ->setSku('simple_on_second_website') + ->setPrice(10) + ->setMetaTitle('meta title2') + ->setMetaKeyword('meta keyword2') + ->setMetaDescription('meta description2') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['is_in_stock' => StockStatusInterface::STATUS_OUT_OF_STOCK]); + +$productRepository->save($product); + +$stockAlert = $stockFactory->create(); +$stockAlert->setCustomerId( + $customer->getId() +)->setProductId( + (int)$productRepository->get($product->getSku())->getId() +)->setWebsiteId( + (int)$secondWebsite->getId() +)->setStoreId( + (int)$storeManager->getStore('fixture_third_store')->getId() +); +$stockResource->save($stockAlert); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php new file mode 100644 index 0000000000000..0fa5f73a7927c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\ProductAlert\Model\ResourceModel\Stock as StockResource; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var StockResource $stockResource */ +$stockResource = $objectManager->get(StockResource::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('simple_on_second_website'); +} catch (NoSuchEntityException $e) { + //already removed +} + + +$stockAlert = $stockFactory->create(); +$stockAlert->deleteCustomer((int)$customer->getId(), (int)$secondWebsite->getId()); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance() + ->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address_rollback.php'); From d866a0b69b35f7207f743d48ad9bcc2c3280f85c Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 4 Jan 2021 18:17:41 +0200 Subject: [PATCH 123/242] MC-40070: Create automated test for: "Try to save product with string type qty value" --- .../Product/Attribute/Backend/StockTest.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php new file mode 100644 index 0000000000000..24d5b668ac09c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Attribute\Backend; + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Model\Product; +use Magento\Eav\Model\Config; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Test class for backend stock attribute model. + * + * @see \Magento\Catalog\Model\Product\Attribute\Backend\Stock + * + * @magentoAppArea adminhtml + */ +class StockTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductInterfaceFactory */ + private $productFactory; + + /** @var Stock */ + private $model; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productFactory = $this->objectManager->get(ProductInterfaceFactory::class); + $this->model = $this->objectManager->get(Stock::class); + $this->model->setAttribute( + $this->objectManager->get(Config::class)->getAttribute(Product::ENTITY, 'quantity_and_stock_status') + ); + } + + /** + * @return void + */ + public function testValidate(): void + { + $this->expectException(LocalizedException::class); + $this->expectErrorMessage((string)__('Please enter a valid number in this field.')); + $product = $this->productFactory->create(); + $product->setQuantityAndStockStatus(['qty' => 'string']); + $this->model->validate($product); + } +} From f5932e2fe2abbd8d011c53cc886d57f5d6464f20 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 5 Jan 2021 08:30:55 +0200 Subject: [PATCH 124/242] MC-40277: Integration test failed \Magento\Catalog\Block\Product\View\Options\Type\DateTest::testToHtmlWithDropDown --- .../Catalog/Block/Product/View/Options/Type/DateTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php index 91a54d8fc13fa..d21fdf190c0b8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php @@ -20,6 +20,7 @@ /** * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DateTest extends TestCase { @@ -96,9 +97,10 @@ protected function tearDown(): void } /** - * @magentoAppArea frontend * @param array $data * @param array $expected + * @magentoAppArea frontend + * @magentoConfigFixture current_store catalog/custom_options/year_range 2020,2030 * @dataProvider toHtmlWithDropDownDataProvider */ public function testToHtmlWithDropDown(array $data, array $expected): void @@ -108,11 +110,12 @@ public function testToHtmlWithDropDown(array $data, array $expected): void } /** - * @magentoAppArea frontend - * @magentoConfigFixture current_store catalog/custom_options/use_calendar 1 * @param array $data * @param array $expected * @param string|null $locale + * @magentoAppArea frontend + * @magentoConfigFixture current_store catalog/custom_options/use_calendar 1 + * @magentoConfigFixture current_store catalog/custom_options/year_range 2020,2030 * @dataProvider toHtmlWithCalendarDataProvider */ public function testToHtmlWithCalendar(array $data, array $expected, ?string $locale = null): void From 0292cb250ec6c9a436486b7e6d1e11c4e3a95286 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 5 Jan 2021 08:54:49 +0200 Subject: [PATCH 125/242] MC-40277: Integration test failed \Magento\Catalog\Block\Product\View\Options\Type\DateTest::testToHtmlWithDropDown --- .../CreateProductAttributeEntityDateTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml index d1f7adb8a902c..9d805b2cf7930 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml @@ -14,8 +14,8 @@ <title value="Admin should be able to create a Date product attribute"/> <description value="Admin should be able to create a Date product attribute"/> <severity value="BLOCKER"/> - <testCaseId value="MC-10895"/> - <group value="Catalog"/> + <testCaseId value="MC-26021"/> + <group value="catalog"/> <group value="mtf_migrated"/> </annotations> @@ -34,7 +34,7 @@ <!--Generate date for use as default value, needs to be MM/d/YYYY and mm/d/yy--> <generateDate date="now" format="m/j/Y" stepKey="generateDefaultDate"/> - <generateDate date="now" format="m/j/y" stepKey="generateDateCompressedFormat"/> + <generateDate date="now" format="n/j/y" stepKey="generateDateCompressedFormat"/> <!--Navigate to Stores > Attributes > Product.--> <actionGroup ref="AdminOpenProductAttributePageActionGroup" stepKey="goToProductAttributes"/> From a13556982cf0d923350aef2f859f21a96e2f597e Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Tue, 5 Jan 2021 12:34:22 +0200 Subject: [PATCH 126/242] Add action items for stale bot comment --- .github/stale.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index 0b9283fde06c7..12874afdb363b 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -39,8 +39,9 @@ staleLabel: "stale issue" # Comment to post when marking as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had - recent activity. It will be closed after 14 days if no further activity occurs. Thank you - for your contributions. + recent activity. It will be closed after 14 days if no further activity occurs. + Is this issue still relevant? If so, what is blocking it? Is there anything you can do to help move it forward? + Thank you for your contributions! # Comment to post when removing the stale label. # unmarkComment: > # Your comment here. From 7a1e8a88f00ceb4ff689e591eeaaa06e62fb336b Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 5 Jan 2021 12:35:05 +0200 Subject: [PATCH 127/242] MC-40061: Create automated test for: "Subscribe to stock price alert" --- .../Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php index d03bc935bcd72..b9ccfd6d52458 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php @@ -60,7 +60,7 @@ protected function setUp(): void * @param string|null $storeCode * @return void */ - public function testGridCollectionWIthStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void + public function testGridCollectionWithStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void { $productId = (int)$this->productRepository->get($sku)->getId(); $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : null; From 181d24c35fe71e8b002bb95d51cc75d7107bb479 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 5 Jan 2021 13:50:34 +0200 Subject: [PATCH 128/242] MC-39636: Create automated test for: "Try to save the category without filling the required fields." --- .../Adminhtml/Category/Save/SaveCategoryTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php index a64e8b769cf23..3a93161517301 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php @@ -103,7 +103,10 @@ public function testTryToCreateCategoryWithEmptyValues(): void 'return_session_messages_only' => false, ]); $this->dispatch('backend/catalog/category/save'); - $message = 'The "Available Product Listing Sort By" attribute is required. Enter and try again.'; - $this->assertSessionMessages($this->equalTo([(string)__($message)]), MessageInterface::TYPE_ERROR); + $message = (string)__( + 'The "%1" attribute is required. Enter and try again.', + 'Available Product Listing Sort By' + ); + $this->assertSessionMessages($this->containsEqual($message), MessageInterface::TYPE_ERROR); } } From af8443c1638b14a2dc09fedc0297c10801f265fb Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Tue, 5 Jan 2021 15:57:28 +0200 Subject: [PATCH 129/242] MC-23915: Wrong currency symbol in creditmemo_grid & sales_order_view > creditmemo grid for subtotal & Shipping and Handling fee --- .../Listing/Column/PurchasedPriceTest.php | 72 ++++++++++++++++--- .../Listing/Column/PurchasedPrice.php | 16 ++++- .../sales_order_creditmemo_grid.xml | 4 +- .../sales_order_view_creditmemo_grid.xml | 4 +- 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php index 6cbfd19f49cdd..a6fc99eac3ed9 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php @@ -11,6 +11,7 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\Processor; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Ui\Component\Listing\Column\Price; use Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice; use PHPUnit\Framework\MockObject\MockObject; @@ -28,6 +29,11 @@ class PurchasedPriceTest extends TestCase */ protected $currencyMock; + /** + * @var OrderRepositoryInterface|MockObject + */ + protected $orderMock; + protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -41,31 +47,60 @@ protected function setUp(): void ->setMethods(['load', 'format']) ->disableOriginalConstructor() ->getMock(); + $this->orderMock = $this->getMockBuilder(OrderRepositoryInterface::class) + ->setMethods(['getList','get','delete','save','getOrderCurrencyCode']) + ->disableOriginalConstructor() + ->getMock(); $this->model = $objectManager->getObject( PurchasedPrice::class, - ['currency' => $this->currencyMock, 'context' => $contextMock] + [ + 'currency' => $this->currencyMock, + 'context' => $contextMock, + 'order' => $this->orderMock, + ] ); } - public function testPrepareDataSource() - { - $itemName = 'itemName'; - $oldItemValue = 'oldItemValue'; - $newItemValue = 'newItemValue'; + /** + * @param string $itemName + * @param string $oldItemValue + * @param string $newItemValue + * @param string|null $orderCurrencyCode + * @dataProvider prepareDataSourceDataProvider + */ + public function testPrepareDataSource( + $itemName, + $oldItemValue, + $newItemValue, + $orderCurrencyCode + ): void { $dataSource = [ 'data' => [ 'items' => [ [ $itemName => $oldItemValue, - 'order_currency_code' => 'US' + 'order_currency_code' => $orderCurrencyCode, + 'order_id' => 1, ] ] ] ]; + if (isset($dataSource['data']['items'][0]['order_currency_code'])) { + $currencyCode = $dataSource['data']['items'][0]['order_currency_code']; + } else { + $currencyCode = 'FR'; + $this->orderMock->expects($this->once()) + ->method('get') + ->willReturnSelf(); + $this->orderMock->expects($this->once()) + ->method('getOrderCurrencyCode') + ->willReturn($currencyCode); + } + $this->currencyMock->expects($this->once()) ->method('load') - ->with($dataSource['data']['items'][0]['order_currency_code']) + ->with($currencyCode) ->willReturnSelf(); $this->currencyMock->expects($this->once()) @@ -77,4 +112,25 @@ public function testPrepareDataSource() $dataSource = $this->model->prepareDataSource($dataSource); $this->assertEquals($newItemValue, $dataSource['data']['items'][0][$itemName]); } + + /** + * @return array + */ + public function prepareDataSourceDataProvider(): array + { + return [ + [ + 'item_name' => 'itemName', + 'old_item_value' => 'oldItemValue', + 'new_item_value' => 'newItemValue', + 'order_currency_code' => 'US', + ], + [ + 'item_name' => 'itemName', + 'old_item_value' => 'oldItemValue', + 'new_item_value' => 'newItemValue', + 'order_currency_code' => null, + ], + ]; + } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php index 966673e5e7f61..1c4426204aea2 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php @@ -9,6 +9,7 @@ use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Directory\Model\Currency; @@ -28,6 +29,11 @@ class PurchasedPrice extends Column */ private $currency; + /** + * @var OrderRepositoryInterface + */ + private $order; + /** * Constructor * @@ -37,6 +43,7 @@ class PurchasedPrice extends Column * @param array $components * @param array $data * @param Currency $currency + * @param OrderRepositoryInterface $order */ public function __construct( ContextInterface $context, @@ -44,11 +51,14 @@ public function __construct( PriceCurrencyInterface $priceFormatter, array $components = [], array $data = [], - Currency $currency = null + Currency $currency = null, + OrderRepositoryInterface $order = null ) { $this->priceFormatter = $priceFormatter; $this->currency = $currency ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(Currency::class); + $this->order = $order ?: \Magento\Framework\App\ObjectManager::getInstance() + ->create(OrderRepositoryInterface::class); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -62,7 +72,9 @@ public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $currencyCode = isset($item['order_currency_code']) ? $item['order_currency_code'] : null; + $currencyCode = isset($item['order_currency_code']) + ? $item['order_currency_code'] + : $this->order->get($item['order_id'])->getOrderCurrencyCode(); $purchaseCurrency = $this->currency->load($currencyCode); $item[$this->getData('name')] = $purchaseCurrency ->format($item[$this->getData('name')], [], false); diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml index 1fc8d41ce0900..a7e79f23b1cca 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml @@ -194,14 +194,14 @@ <visible>false</visible> </settings> </column> - <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <settings> <filter>textRange</filter> <label translate="true">Subtotal</label> <visible>false</visible> </settings> </column> - <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <settings> <filter>textRange</filter> <label translate="true">Shipping & Handling</label> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml index 09be15c5a3cf9..16a7e00b24bb3 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml @@ -207,14 +207,14 @@ <visible>false</visible> </settings> </column> - <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <settings> <filter>textRange</filter> <label translate="true">Subtotal</label> <visible>false</visible> </settings> </column> - <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <settings> <filter>textRange</filter> <label translate="true">Shipping & Handling</label> From 6db8da7e8d8e5d0df516b501cf2473b43fcc4c8b Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Wed, 6 Jan 2021 10:18:37 +0200 Subject: [PATCH 130/242] MC-39891: Arabic text in invoice is not displayed correctly --- app/code/Magento/Sales/Model/RtlTextHandler.php | 2 +- app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/RtlTextHandler.php b/app/code/Magento/Sales/Model/RtlTextHandler.php index cfb88dc63f58b..b943320e0f897 100644 --- a/app/code/Magento/Sales/Model/RtlTextHandler.php +++ b/app/code/Magento/Sales/Model/RtlTextHandler.php @@ -48,7 +48,7 @@ public function reverseRtlText(string $string): string for ($i = 0; $i < $splitTextAmount; $i++) { if ($this->isRtlText($splitText[$i])) { - for ($j = $i + 1; $j < $splitTextAmount; $j++) { + for ($j = $i; $j < $splitTextAmount; $j++) { $tmp = $this->isRtlText($splitText[$j]) ? $this->stringUtils->strrev($splitText[$j]) : $splitText[$j]; $splitText[$j] = $this->isRtlText($splitText[$i]) diff --git a/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php b/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php index 2faeb17dc2395..1a8159dbf4cbb 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php @@ -62,6 +62,7 @@ public function provideRtlTexts(): array ['Herr Prof. Dr. Gerald Schüler B.A.', false],//German ['نديم مقداد نعمان القحطاني', true],//Arabic ['شهاب الفرحان', true],//Arabic + ['مرحبا ماجنت اثنان', true],//Arabic ['צבר קרליבך', true],//Hebrew ['גורי מייזליש', true],//Hebrew ['اتابک بهشتی', true],//Persian From 6390bbf464ded44c53d8fa96e3e12442da5bd4b1 Mon Sep 17 00:00:00 2001 From: Sergiy Vasiutynskyi <s.vasiutynskyi@atwix.com> Date: Wed, 6 Jan 2021 09:56:44 +0200 Subject: [PATCH 131/242] Removed usage or changed value of CliIndexerReindexActionGroup action group for CatalogRule, Downloadable and Indexer modules --- ...dminApplyCatalogPriceRuleByProductAttributeTest.xml | 5 +---- .../Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml | 4 +--- ...RuleForConfigurableProductWithSpecialPricesTest.xml | 5 +---- .../AdminCreateCatalogPriceRuleByPercentTest.xml | 5 +---- ...AdminCreateCatalogPriceRuleForCustomerGroupTest.xml | 5 +---- ...talogPriceRuleEntityFromConfigurableProductTest.xml | 10 ++-------- ...leteCatalogPriceRuleEntityFromSimpleProductTest.xml | 5 +---- .../Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml | 2 +- ...nEnableAttributeIsUndefinedCatalogPriceRuleTest.xml | 8 ++------ ...yCatalogRuleForSimpleAndConfigurableProductTest.xml | 4 +--- ...alogRuleForSimpleProductForNewCustomerGroupTest.xml | 4 +--- ...upMembershipArePersistedUnderLongTermCookieTest.xml | 5 +---- .../Mftf/Test/StorefrontInactiveCatalogRuleTest.xml | 5 +---- ...reateDownloadableProductWithDefaultSetLinksTest.xml | 9 ++------- .../Test/AdminSystemIndexManagementGridChangesTest.xml | 8 ++------ 15 files changed, 19 insertions(+), 65 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogPriceRuleByProductAttributeTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogPriceRuleByProductAttributeTest.xml index 547ef356f099d..724664917fecc 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogPriceRuleByProductAttributeTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogPriceRuleByProductAttributeTest.xml @@ -154,10 +154,7 @@ <argument name="discountAmount" value="{{SimpleCatalogPriceRule.discount_amount}}"/> </actionGroup> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <!-- Run cron --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value="catalogrule_rule"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Open first simple product page on storefront --> <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="openFirstSimpleProductPage"> <argument name="productUrlKey" value="$createFirstProduct.custom_attributes[url_key]$"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml index e6b825ff3cf70..3109c56122d1b 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml @@ -77,9 +77,7 @@ <!-- 3. Save and apply the new catalog price rule --> <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApply"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml index 1de036d1026dd..97e93c8f762c5 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleForConfigurableProductWithSpecialPricesTest.xml @@ -126,10 +126,7 @@ <!-- Save and apply the new catalog price rule --> <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <!-- Reindex and flash cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleByPercentTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleByPercentTest.xml index d45c3af1c2da0..946a25d721cba 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleByPercentTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleByPercentTest.xml @@ -24,10 +24,7 @@ <requiredEntity createDataKey="createCategory"/> </createData> - <!-- Perform reindex and flush cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleForCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleForCustomerGroupTest.xml index 3c08fbdf641e4..e55cabd506466 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleForCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest/AdminCreateCatalogPriceRuleForCustomerGroupTest.xml @@ -48,10 +48,7 @@ <!--<click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApply"/>--> <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccess"/> - <!-- Perform reindex and flush cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromConfigurableProductTest.xml index 7247d61bea87c..831470e0d64ca 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromConfigurableProductTest.xml @@ -71,10 +71,7 @@ <requiredEntity createDataKey="createConfigChildProduct2"/> </createData> - <!-- Perform reindex and flush cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> @@ -117,10 +114,7 @@ <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> <see selector="{{AdminMessagesSection.success}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> - <!-- Reindex --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromSimpleProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromSimpleProductTest.xml index a3b1729102390..5a62b1a373f94 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromSimpleProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest/AdminDeleteCatalogPriceRuleEntityFromSimpleProductTest.xml @@ -59,10 +59,7 @@ <!-- Assert that the Success message is present after the delete --> <see selector="{{AdminMessagesSection.success}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> - <!-- Reindex --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml index 64fe4d8a130a7..d03ca6b22d66a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml @@ -84,7 +84,7 @@ <!-- Apply and flush the cache --> <click selector="{{AdminCatalogPriceRuleGrid.applyRules}}" stepKey="clickApplyRules"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="catalog_product_price"/> </actionGroup> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml index 745025073dceb..da62981c99202 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminEnableAttributeIsUndefinedCatalogPriceRuleTest.xml @@ -79,9 +79,7 @@ <argument name="targetSelectValue" value="is undefined"/> </actionGroup> <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> @@ -129,9 +127,7 @@ <argument name="targetSelectValue" value="is undefined"/> </actionGroup> <click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="clickSaveAndApplyRules1"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexSecondTime"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindexSecondTime"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheSecondTime"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml index 1651f8425ec1c..c3690e72e084f 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleAndConfigurableProductTest.xml @@ -112,9 +112,7 @@ <!-- Save and apply the new catalog price rule --> <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml index a40bf63c5a388..3b7c9c181f1b1 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/ApplyCatalogRuleForSimpleProductForNewCustomerGroupTest.xml @@ -71,9 +71,7 @@ <!-- Save and apply the new catalog price rule --> <actionGroup ref="SaveAndApplyCatalogPriceRuleActionGroup" stepKey="saveAndApplyCatalogPriceRule"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Navigate to category on store front --> <amOnPage url="{{StorefrontProductPage.url($createCategory.name$)}}" stepKey="goToCategoryPage"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml index b678e379a603d..702e046272cb4 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/CatalogPriceRuleAndCustomerGroupMembershipArePersistedUnderLongTermCookieTest.xml @@ -40,10 +40,7 @@ <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="clickSaveAndApplyRule"/> - <!-- Perform reindex --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value="catalogrule_rule"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> </before> <after> <createData entity="PersistentConfigDefault" stepKey="setDefaultPersistentState"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml index bebf6ce5302d6..6a09f870705d2 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml @@ -33,10 +33,7 @@ </actionGroup> <actionGroup ref="AdminCatalogPriceRuleFillActionsActionGroup" stepKey="fillActionsForThirdPriceRule"/> <actionGroup ref="AdminCatalogPriceRuleSaveAndApplyActionGroup" stepKey="saveAndApplyFirstPriceRule"/> - <!-- Perform reindex --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> </before> <after> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml index e711add69b8c8..43f2f07b83cde 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/AdminCreateDownloadableProductWithDefaultSetLinksTest.xml @@ -23,10 +23,7 @@ <magentoCLI stepKey="addDownloadableDomain" command="downloadable:domains:add static.magento.com"/> <!-- Create category --> <createData entity="SimpleSubCategory" stepKey="createCategory"/> - <!-- Reindex and clear page cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value="full_page"/> </actionGroup> @@ -79,9 +76,7 @@ <!-- Save product --> <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementGridChangesTest.xml b/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementGridChangesTest.xml index 51cf4aa26a1b1..adb0b9d059d81 100644 --- a/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementGridChangesTest.xml +++ b/app/code/Magento/Indexer/Test/Mftf/Test/AdminSystemIndexManagementGridChangesTest.xml @@ -23,9 +23,7 @@ <!--Open Index Management Page and Select Index mode "Update by Schedule" --> <magentoCLI command="indexer:set-mode" arguments="schedule" stepKey="setIndexerModeSchedule"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="indexerReindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="indexerReindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> @@ -34,9 +32,7 @@ <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <magentoCLI command="indexer:set-mode" arguments="realtime" stepKey="setIndexerModeRealTime"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="indexerReindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="indexerReindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> From 8b4e8b5c81a0faa6435290ce1607cf707cd1977a Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Wed, 6 Jan 2021 10:27:22 +0200 Subject: [PATCH 132/242] Test refactoring --- ...IdAtAccountCreateWithMultishipmentTest.xml | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) rename app/code/Magento/{Multishipping => Customer}/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml (81%) diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml similarity index 81% rename from app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml rename to app/code/Magento/Customer/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml index efaf4d7dc639d..b04ac0f4727d0 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml @@ -20,18 +20,23 @@ </annotations> <before> <magentoCLI command="config:set customer/create_account/vat_frontend_visibility 1" stepKey="showVatNumberOnStorefrontYes"/> - <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheBefore"> - <argument name="tags" value="config"/> - </actionGroup> - <createData stepKey="category" entity="SimpleSubCategory"/> - <createData stepKey="product1" entity="SimpleProduct"> + <createData entity="SimpleSubCategory" stepKey="category"/> + <createData entity="SimpleProduct" stepKey="product"> <requiredEntity createDataKey="category"/> </createData> </before> + <after> + <magentoCLI command="config:set customer/create_account/vat_frontend_visibility 0" stepKey="showVatNumberOnStorefrontNo"/> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfter"> + <argument name="tags" value="config"/> + </actionGroup> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <deleteData createDataKey="product" stepKey="deleteproduct"/> + </after> <!-- Add product to the cart --> - <amOnPage url="$$product1.name$$.html" stepKey="goToProductPage"/> + <amOnPage url="$$product.name$$.html" stepKey="goToProductPage"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> - <argument name="productName" value="$$product1.name$$"/> + <argument name="productName" value="$$product.name$$"/> </actionGroup> <!-- Check Out with Multiple Addresses --> <actionGroup ref="StorefrontOpenCartFromMinicartActionGroup" stepKey="openCart"/> @@ -43,13 +48,5 @@ <waitForPageLoad stepKey="waitForCreateAccountPageToLoad"/> <!--Check the VAT Number field--> <seeElement selector="{{StorefrontCustomerAddressSection.vatId}}" stepKey="assertVatIdField"/> - <after> - <magentoCLI command="config:set customer/create_account/vat_frontend_visibility 0" stepKey="showVatNumberOnStorefrontNo"/> - <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfter"> - <argument name="tags" value="config"/> - </actionGroup> - <deleteData stepKey="deleteCategory" createDataKey="category"/> - <deleteData stepKey="deleteProduct1" createDataKey="product1"/> - </after> </test> </tests> From f001e235f5ab64c825b0881e5bf645b0775dd6f7 Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Wed, 6 Jan 2021 10:35:58 +0200 Subject: [PATCH 133/242] MC-24772: After choosing "Web Site" as default, where the "Store View" is disabled, the website is crashing --- .../Controller/Adminhtml/System/Store/Save.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php index b67f1f23f16ba..8f9ff4523f4d9 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php @@ -33,6 +33,18 @@ private function processWebsiteSave($postData) $websiteModel->setId(null); } + $groupModel = $this->_objectManager->create(\Magento\Store\Model\Group::class); + $groupModel->load($websiteModel->getDefaultGroupId()); + + $storeModel = $this->_objectManager->create(\Magento\Store\Model\Store::class); + $storeModel->load($groupModel->getDefaultStoreId()); + + if ($websiteModel->getIsDefault() && !$storeModel->isActive()) { + throw new \Magento\Framework\Exception\LocalizedException( + __("Please enable your Store View before using this Web Site as Default") + ); + } + $websiteModel->save(); $this->messageManager->addSuccessMessage(__('You saved the website.')); @@ -99,6 +111,7 @@ private function processGroupSave($postData) __('An inactive store view cannot be saved as default store view') ); } + $groupModel->save(); $this->messageManager->addSuccessMessage(__('You saved the store.')); From 73f9e9fe1b725ac265c034586939157af38f3c80 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Wed, 6 Jan 2021 11:19:27 +0200 Subject: [PATCH 134/242] MC-35690: [B2B] Unexpected results of editing of a Bundle Product in the Shopping Cart, added from a Requisition List --- .../Catalog/Product/View/Type/Bundle.php | 4 -- .../Bundle/Model/CartItemProcessor.php | 11 +++--- .../Catalog/Product/View/Type/BundleTest.php | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index 2e9b8ba413af3..635811e3d0f81 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -184,10 +184,6 @@ public function getJsonConfig() $configValue = $preConfiguredValues->getData('bundle_option/' . $optionId); if ($configValue) { $defaultValues[$optionId] = $configValue; - $configQty = $preConfiguredValues->getData('bundle_option_qty/' . $optionId); - if ($configQty) { - $options[$optionId]['selections'][$configValue]['qty'] = $configQty; - } } $options = $this->processOptions($optionId, $options, $preConfiguredValues); } diff --git a/app/code/Magento/Bundle/Model/CartItemProcessor.php b/app/code/Magento/Bundle/Model/CartItemProcessor.php index dc51f3e3969b4..0a9fb6e995e5a 100644 --- a/app/code/Magento/Bundle/Model/CartItemProcessor.php +++ b/app/code/Magento/Bundle/Model/CartItemProcessor.php @@ -51,7 +51,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc */ public function convertToBuyRequest(CartItemInterface $cartItem) { @@ -73,7 +73,7 @@ public function convertToBuyRequest(CartItemInterface $cartItem) } /** - * {@inheritdoc} + * @inheritDoc * @SuppressWarnings(PHPMD.NPathComplexity) */ public function processOptions(CartItemInterface $cartItem) @@ -83,20 +83,21 @@ public function processOptions(CartItemInterface $cartItem) } $productOptions = []; $bundleOptions = $cartItem->getBuyRequest()->getBundleOption(); - $bundleOptionsQty = $cartItem->getBuyRequest()->getBundleOptionQty(); + $bundleOptionsQty = $cartItem->getBuyRequest()->getBundleOptionQty() ?? []; if (is_array($bundleOptions)) { foreach ($bundleOptions as $optionId => $optionSelections) { if (empty($optionSelections)) { continue; } $optionSelections = is_array($optionSelections) ? $optionSelections : [$optionSelections]; - $optionQty = isset($bundleOptionsQty[$optionId]) ? $bundleOptionsQty[$optionId] : 1; /** @var \Magento\Bundle\Api\Data\BundleOptionInterface $productOption */ $productOption = $this->bundleOptionFactory->create(); $productOption->setOptionId($optionId); $productOption->setOptionSelections($optionSelections); - $productOption->setOptionQty($optionQty); + if (is_array($bundleOptionsQty) && isset($bundleOptionsQty[$optionId])) { + $productOption->setOptionQty($bundleOptionsQty[$optionId]); + } $productOptions[] = $productOption; } 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 517109625424c..a90c971b0fd0e 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 @@ -8,14 +8,17 @@ namespace Magento\Bundle\Block\Catalog\Product\View\Type; use Magento\Bundle\Model\Product\Price; +use Magento\Bundle\Model\Product\Type; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Helper\Product as ProductHelper; 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; +use Magento\Framework\DataObject\Factory as DataObjectFactory; /** * Class checks bundle product view behaviour @@ -87,6 +90,41 @@ public function testGetJsonConfig(): void $this->assertEquals(5, $selection['prices']['finalPrice']['amount']); } + /** + * Check that selection qty is calculated correctly for Bundle config. + * + * @return void + */ + public function testGetJsonConfigWithPreconfiguredValues(): void + { + $optionQty = 3; + $bundleProduct = $this->productRepository->get('bundle-product'); + $bundleSelection = $this->productRepository->get('simple'); + + /** @var Type $typeInstance */ + $typeInstance = $bundleProduct->getTypeInstance(); + $typeInstance->setStoreFilter($bundleProduct->getStoreId(), $bundleProduct); + $optionCollection = $typeInstance->getOptionsCollection($bundleProduct); + $optionId = $optionCollection->getFirstItem()->getId(); + $preconfiguredValues = $this->objectManager->get(DataObjectFactory::class)->create([ + 'bundle_option' => [ + $optionId => [$bundleSelection->getId()] + ], + 'bundle_option_qty' => [ + $optionId => $optionQty + ], + ]); + + /** @var ProductHelper $productHelper */ + $productHelper = $this->objectManager->get(ProductHelper::class); + $productHelper->prepareProductOptions($bundleProduct, $preconfiguredValues); + $this->registerProduct($bundleProduct); + + $resultConfig = $this->json->unserialize($this->block->getJsonConfig()); + $this->assertTrue(isset($resultConfig['options'][$optionId]['selections'][$optionId]['qty'])); + $this->assertEquals($optionQty, $resultConfig['options'][$optionId]['selections'][$optionId]['qty']); + } + /** * @dataProvider isSalableForStockStatusProvider * From 1f9802ddb6bf67cc9d70d9e468787f1c1e1e27f2 Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Wed, 6 Jan 2021 14:37:12 +0200 Subject: [PATCH 135/242] Test refactoring --- .../StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/code/Magento/{Customer => Multishipping}/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml (100%) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml similarity index 100% rename from app/code/Magento/Customer/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml rename to app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml From 07f0fad1acca3d00f216b33721f8714069de0098 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 6 Jan 2021 14:43:54 +0200 Subject: [PATCH 136/242] MC-23915: Wrong currency symbol in creditmemo_grid & sales_order_view > creditmemo grid for subtotal & Shipping and Handling fee --- .../Listing/Column/PurchasedPriceTest.php | 14 +++++++------- .../Ui/Component/Listing/Column/PurchasedPrice.php | 13 ++++++------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php index a6fc99eac3ed9..cc1408ecd816e 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php @@ -22,17 +22,17 @@ class PurchasedPriceTest extends TestCase /** * @var Price */ - protected $model; + private $model; /** * @var Currency|MockObject */ - protected $currencyMock; + private $currencyMock; /** * @var OrderRepositoryInterface|MockObject */ - protected $orderMock; + private $orderRepository; protected function setUp(): void { @@ -47,7 +47,7 @@ protected function setUp(): void ->setMethods(['load', 'format']) ->disableOriginalConstructor() ->getMock(); - $this->orderMock = $this->getMockBuilder(OrderRepositoryInterface::class) + $this->orderRepository = $this->getMockBuilder(OrderRepositoryInterface::class) ->setMethods(['getList','get','delete','save','getOrderCurrencyCode']) ->disableOriginalConstructor() ->getMock(); @@ -56,7 +56,7 @@ protected function setUp(): void [ 'currency' => $this->currencyMock, 'context' => $contextMock, - 'order' => $this->orderMock, + 'order' => $this->orderRepository, ] ); } @@ -90,10 +90,10 @@ public function testPrepareDataSource( $currencyCode = $dataSource['data']['items'][0]['order_currency_code']; } else { $currencyCode = 'FR'; - $this->orderMock->expects($this->once()) + $this->orderRepository->expects($this->once()) ->method('get') ->willReturnSelf(); - $this->orderMock->expects($this->once()) + $this->orderRepository->expects($this->once()) ->method('getOrderCurrencyCode') ->willReturn($currencyCode); } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php index 1c4426204aea2..fc38d4d010b8c 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php @@ -32,7 +32,7 @@ class PurchasedPrice extends Column /** * @var OrderRepositoryInterface */ - private $order; + private $orderRepository; /** * Constructor @@ -43,7 +43,7 @@ class PurchasedPrice extends Column * @param array $components * @param array $data * @param Currency $currency - * @param OrderRepositoryInterface $order + * @param OrderRepositoryInterface $orderRepository */ public function __construct( ContextInterface $context, @@ -52,12 +52,12 @@ public function __construct( array $components = [], array $data = [], Currency $currency = null, - OrderRepositoryInterface $order = null + OrderRepositoryInterface $orderRepository = null ) { $this->priceFormatter = $priceFormatter; $this->currency = $currency ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(Currency::class); - $this->order = $order ?: \Magento\Framework\App\ObjectManager::getInstance() + $this->orderRepository = $orderRepository ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(OrderRepositoryInterface::class); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -72,9 +72,8 @@ public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $currencyCode = isset($item['order_currency_code']) - ? $item['order_currency_code'] - : $this->order->get($item['order_id'])->getOrderCurrencyCode(); + $currencyCode = $item['order_currency_code'] + ?? $this->orderRepository->get($item['order_id'])->getOrderCurrencyCode(); $purchaseCurrency = $this->currency->load($currencyCode); $item[$this->getData('name')] = $purchaseCurrency ->format($item[$this->getData('name')], [], false); From af19a21e3a3bf79ef9349cc7874753c8fc13b896 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Wed, 6 Jan 2021 18:39:03 +0200 Subject: [PATCH 137/242] MC-39551: Create automated test for: "On category page switch to list mode" --- .../Block/Product/ProductList/ToolbarTest.php | 141 ++++++++++++++++-- 1 file changed, 130 insertions(+), 11 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php index 7fa54f8af5b5c..028ac72dbc4ed 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php @@ -3,28 +3,147 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Block\Product\ProductList; -class ToolbarTest extends \PHPUnit\Framework\TestCase +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\Text; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Helper\Xpath; + +/** + * Checks product list toolbar. + * + * @see \Magento\Catalog\Block\Product\ProductList\Toolbar + * @magentoAppArea frontend + * @magentoDbIsolation enabled + */ +class ToolbarTest extends TestCase { + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + } + public function testGetPagerHtml() { - /** @var $layout \Magento\Framework\View\Layout */ - $layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class - ); - /** @var $block \Magento\Catalog\Block\Product\ProductList\Toolbar */ - $block = $layout->createBlock(\Magento\Catalog\Block\Product\ProductList\Toolbar::class, 'block'); - /** @var $childBlock \Magento\Framework\View\Element\Text */ - $childBlock = $layout->addBlock( - \Magento\Framework\View\Element\Text::class, + /** @var $block Toolbar */ + $block = $this->layout->createBlock(Toolbar::class, 'block'); + /** @var $childBlock Text */ + $childBlock = $this->layout->addBlock( + Text::class, 'product_list_toolbar_pager', 'block' ); - $expectedHtml = '<b>Any text there</b>'; $this->assertNotEquals($expectedHtml, $block->getPagerHtml()); $childBlock->setText($expectedHtml); $this->assertEquals($expectedHtml, $block->getPagerHtml()); } + + /** + * @magentoConfigFixture default_store catalog/frontend/list_mode grid + */ + public function testToHtmlGridOnly(): void + { + $block = $this->layout->createBlock(Toolbar::class, 'block'); + $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/*[@data-value="grid"]', + $block->toHtml() + ) + ); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/*[@data-value="list"]', + $block->toHtml() + ) + ); + } + + /** + * @magentoConfigFixture default_store catalog/frontend/list_mode list + */ + public function testToHtmlListOnly(): void + { + $block = $this->layout->createBlock(Toolbar::class, 'block'); + $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/*[@data-value="grid"]', + $block->toHtml() + ) + ); + $this->assertEquals( + 0, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/*[@data-value="list"]', + $block->toHtml() + ) + ); + } + + /** + * @magentoConfigFixture default_store catalog/frontend/list_mode grid-list + */ + public function testToHtmlGridList(): void + { + $block = $this->layout->createBlock(Toolbar::class, 'block'); + $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/strong[@data-value="grid" and contains(@class, "active")]', + $block->toHtml() + ) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/a[@data-value="list"]', + $block->toHtml() + ) + ); + } + + /** + * @magentoConfigFixture default_store catalog/frontend/list_mode list-grid + */ + public function testToHtmlListGrid(): void + { + $block = $this->layout->createBlock(Toolbar::class, 'block'); + $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/strong[@data-value="list" and contains(@class, "active")]', + $block->toHtml() + ) + ); + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath( + '//div[contains(@class, "modes")]/a[@data-value="grid"]', + $block->toHtml() + ) + ); + } } From 9e627bfda8efb715ebf84bbeee44c6d2e7076e34 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 8 Jan 2021 11:52:59 +0200 Subject: [PATCH 138/242] MC-40073: Create automated test for: "Guest and customer comparison lists merging" --- .../Compare/BindCustomerLoginObserverTest.php | 125 ++++++++++++++++++ ...tomer_compare_list_with_simple_product.php | 32 +++++ ...pare_list_with_simple_product_rollback.php | 11 ++ .../Catalog/_files/visitor_compare_list.php | 23 ++++ .../_files/visitor_compare_list_rollback.php | 10 ++ 5 files changed, 201 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php new file mode 100644 index 0000000000000..c177c902d9d49 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Observer\Compare; + +use Magento\Catalog\Model\Product\Compare\ListCompareFactory; +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Visitor; +use Magento\Eav\Model\Entity\Collection\AbstractCollection; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks customer and visitor compare list merging after customer login + * + * @see \Magento\Catalog\Observer\Compare\BindCustomerLoginObserver + * + * @magentoAppArea frontend + * @magentoDbIsolation enabled + */ +class BindCustomerLoginObserverTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Session */ + private $session; + + /** @var Visitor */ + private $visitor; + + /** @var ListCompareFactory */ + private $listCompareFactory; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->session = $this->objectManager->get(Session::class); + $this->visitor = $this->objectManager->get(Visitor::class); + $this->listCompareFactory = $this->objectManager->get(ListCompareFactory::class); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/visitor_compare_list.php + * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void + */ + public function testExecute(): void + { + $this->visitor->setId(123); + $this->session->loginById(1); + $this->assertCustomerItems(1, ['simple']); + $this->assertVisitorItems(123, []); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/customer_compare_list_with_simple_product.php + * @magentoDataFixture Magento/Catalog/_files/product_in_compare_list_with_customer.php + * @magentoDataFixture Magento/Catalog/_files/visitor_compare_list.php + * + * @return void + */ + public function testExecuteWithSameProducts(): void + { + $this->visitor->setId(123); + $this->session->loginById(1); + $this->assertCustomerItems(1, ['simple', 'simple2']); + $this->assertVisitorItems(123, []); + } + + /** + * Check customer compare items + * + * @param int $customerId + * @param array $expectedProductSkus + * @return void + */ + private function assertCustomerItems(int $customerId, array $expectedProductSkus): void + { + $collection = $this->listCompareFactory->create()->getItemCollection()->useProductItem() + ->setCustomerId($customerId); + $this->checkCollection($collection, $expectedProductSkus); + } + + /** + * Checks visitor compare items + * + * @param int $visitorId + * @param array $expectedProductSkus + * @return void + */ + private function assertVisitorItems(int $visitorId, array $expectedProductSkus): void + { + $collection = $this->listCompareFactory->create()->getItemCollection()->useProductItem() + ->setVisitorId($visitorId); + $collection->addFieldToFilter('customer_id', ['null' => true]); + $this->checkCollection($collection, $expectedProductSkus); + } + + /** + * Check collection + * + * @param AbstractCollection $collection + * @param array $expectedSkus + * @return void + */ + private function checkCollection(AbstractCollection $collection, array $expectedSkus): void + { + $this->assertCount(count($expectedSkus), $collection); + foreach ($expectedSkus as $expectedSku) { + $this->assertNotNull($collection->getItemByColumnValue('sku', $expectedSku)); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product.php new file mode 100644 index 0000000000000..de8d91d30f15e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Model\Product\Compare\ListCompare; +use Magento\Catalog\Model\Product\Compare\ListCompareFactory; +use Magento\Customer\Model\Session; +use Magento\Customer\Model\Visitor; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var Session $session */ +$session = $objectManager->get(Session::class); + +try { + $session->loginById(1); + /** @var Visitor $visitor */ + $visitor = $objectManager->get(Visitor::class); + $visitor->setVisitorId(1); + /** @var ListCompare $compareList */ + $compareList = $objectManager->get(ListCompareFactory::class)->create(); + $compareList->addProduct(1); +} finally { + $session->logout(); +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product_rollback.php new file mode 100644 index 0000000000000..0931d881a6fdc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/customer_compare_list_with_simple_product_rollback.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php new file mode 100644 index 0000000000000..da5089f25e027 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Model\Product\Compare\ListCompare; +use Magento\Catalog\Model\Product\Compare\ListCompareFactory; +use Magento\Customer\Model\Visitor; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); + +$objectManager = Bootstrap::getObjectManager(); + +/** @var Visitor $visitor */ +$visitor = $objectManager->get(Visitor::class); +$visitor->setVisitorId(123); +/** @var ListCompare $compareList */ +$compareList = $objectManager->get(ListCompareFactory::class)->create(); +$compareList->addProduct(1); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list_rollback.php new file mode 100644 index 0000000000000..328c1e229da5c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list_rollback.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); From be1d994cb78a76046e562c04d4f4c130d2e64127 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Fri, 8 Jan 2021 14:04:31 +0200 Subject: [PATCH 139/242] MC-39551: Create automated test for: "On category page switch to list mode" --- .../Magento/Catalog/Block/Product/ProductList/ToolbarTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php index 028ac72dbc4ed..392e77d60d3e3 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php @@ -20,6 +20,7 @@ * @see \Magento\Catalog\Block\Product\ProductList\Toolbar * @magentoAppArea frontend * @magentoDbIsolation enabled + * @magentoAppIsolation enabled */ class ToolbarTest extends TestCase { From 724dd05d7885f6fd7728672a24dab3669a0498b7 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Fri, 8 Jan 2021 14:35:20 +0200 Subject: [PATCH 140/242] MC-39717: Create automated test for: "Filter products in the category grid(admin)" --- .../Adminhtml/Category/Tab/ProductTest.php | 177 ++++++++++++++++++ .../Adminhtml/Category/GridTest.php | 33 ++++ 2 files changed, 210 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Category/Tab/ProductTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/GridTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Category/Tab/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Category/Tab/ProductTest.php new file mode 100644 index 0000000000000..1dcf94d2fd20c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Category/Tab/ProductTest.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Adminhtml\Category\Tab; + +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection; +use Magento\Framework\Registry; +use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; +use Magento\Framework\ObjectManagerInterface; +use Magento\Catalog\Api\Data\ProductInterface; + +/** + * Checks grid data on the tab 'Products in Category' category view page. + * + * @see \Magento\Catalog\Block\Adminhtml\Category\Tab\Product + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class ProductTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var LayoutInterface */ + private $layout; + + /** @var CategoryRepositoryInterface */ + private $categoryRepository; + + /** @var Registry */ + private $registry; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->categoryRepository = $this->objectManager->get(CategoryRepositoryInterface::class); + $this->registry = $this->objectManager->get(Registry::class); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + $this->registry->unregister('category'); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category_with_two_products.php + * @magentoDataFixture Magento/Catalog/_files/product_associated.php + * @magentoDataFixture Magento/Catalog/_files/simple_product_disabled.php + * @dataProvider optionsFilterProvider + * @param string $filterColumn + * @param int $categoryId + * @param int $storeId + * @param array $items + * @return void + */ + public function testFilterProductInCategory(string $filterColumn, int $categoryId, int $storeId, array $items): void + { + $collection = $this->filterProductInGrid($filterColumn, $categoryId, $storeId); + $this->assertCount(count($items), $collection->getItems()); + foreach ($items as $item) { + $this->assertNotNull($collection->getItemByColumnValue(ProductInterface::SKU, $item)); + } + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category.php + * @return void + */ + public function testEmptyProductIdColumnFilter(): void + { + $this->assertCount(0, $this->filterProductInGrid('in_category=1', 333, 1)->getItems()); + } + + /** + * Different variations for filter test. + * + * @return array + */ + public function optionsFilterProvider(): array + { + return [ + 'filter_yes' => [ + 'filter_column' => 'in_category=1', + 'id_category' => 333, + 'store_id' => 1, + 'items' => [ + 'simple333', + 'simple2', + ], + ], + 'filter_no' => [ + 'filter_column' => 'in_category=0', + 'id_category' => 333, + 'store_id' => 1, + 'items' => [ + 'product_disabled', + 'simple', + ], + ], + 'filter_any' => [ + 'filter_column' => "", + 'id_category' => 333, + 'store_id' => 1, + 'items' => [ + 'product_disabled', + 'simple333', + 'simple2', + 'simple', + ], + ], + 'flag_status' => [ + 'filter_column' => 'status=1', + 'id_category' => 333, + 'store_id' => 1, + 'items' => [ + 'simple333', + 'simple2', + 'simple', + ], + ], + ]; + } + + /** + * Filter product in grid + * + * @param string $filterOption + * @param int $categoryId + * @param int $storeId + * @return AbstractCollection + */ + private function filterProductInGrid(string $filterOption, int $categoryId, int $storeId): AbstractCollection + { + $this->registerCategory($this->categoryRepository->get($categoryId)); + $block = $this->layout->createBlock(Product::class); + $block->getRequest()->setParams([ + 'id' => $categoryId, + 'filter' => base64_encode($filterOption), + 'store' => $storeId, + ]); + $block->toHtml(); + + return $block->getCollection(); + } + + /** + * Register category in registry + * + * @param CategoryInterface $category + * @return void + */ + private function registerCategory(CategoryInterface $category): void + { + $this->registry->unregister('category'); + $this->registry->register('category', $category); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/GridTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/GridTest.php new file mode 100644 index 0000000000000..ce4d4a087a90b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/GridTest.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Category; + +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\TestFramework\Helper\Xpath; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Tests for catalog category grid controller + * + * @see \Magento\Catalog\Controller\Adminhtml\Category\Grid + * @magentoAppArea adminhtml + */ +class GridTest extends AbstractBackendController +{ + /** + * @magentoDbIsolation enabled + * @return void + */ + public function testRenderCategoryGrid(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->dispatch('backend/catalog/category/grid'); + $content = $this->getResponse()->getBody(); + $this->assertEquals(1, Xpath::getElementsCountForXpath('//div[@id="catalog_category_products"]', $content)); + } +} From d523c825797d466bd6353821cfefd14f3038e430 Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Wed, 6 Jan 2021 08:47:54 +0200 Subject: [PATCH 141/242] MC-38025: FPT disappears when switching back to the cart page --- .../Magento/Quote/Model/Quote/Address.php | 8 +- .../Weee/Model/Total/Quote/WeeeTax.php | 58 +++++---- .../Weee/Model/Total/Quote/CalculateTest.php | 80 ++++++++++++ .../Weee/_files/quote_multishipping.php | 117 ++++++++++++++++++ .../_files/quote_multishipping_rollback.php | 31 +++++ 5 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Weee/Model/Total/Quote/CalculateTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping.php create mode 100644 dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping_rollback.php diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php index 1ad98aa3e0263..6a06deb9cbbef 100644 --- a/app/code/Magento/Quote/Model/Quote/Address.php +++ b/app/code/Magento/Quote/Model/Quote/Address.php @@ -1115,7 +1115,13 @@ public function requestShippingRates(AbstractItem $item = null) */ public function getTotals() { - $totalsData = array_merge($this->getData(), ['address_quote_items' => $this->getAllItems()]); + $totalsData = array_merge( + $this->getData(), + [ + 'address_quote_items' => $this->getAllItems(), + 'quote_items' => $this->getQuote()->getAllItems(), + ] + ); $totals = $this->totalsReader->fetch($this->getQuote(), $totalsData); foreach ($totals as $total) { $this->addTotal($total); diff --git a/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php b/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php index c6825958d2178..7429f875eda98 100644 --- a/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php +++ b/app/code/Magento/Weee/Model/Total/Quote/WeeeTax.php @@ -5,8 +5,11 @@ */ namespace Magento\Weee\Model\Total\Quote; +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\Store\Model\Store; use Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector; class WeeeTax extends Weee @@ -14,19 +17,19 @@ class WeeeTax extends Weee /** * Collect Weee taxes amount and prepare items prices for taxation and discount * - * @param \Magento\Quote\Model\Quote $quote - * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface|\Magento\Quote\Model\Quote\Address $shippingAssignment - * @param \Magento\Quote\Model\Quote\Address\Total $total + * @param Quote $quote + * @param ShippingAssignmentInterface|Address $shippingAssignment + * @param Total $total * @return $this * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ 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 ) { - \Magento\Quote\Model\Quote\Address\Total\AbstractTotal::collect($quote, $shippingAssignment, $total); + AbstractTotal::collect($quote, $shippingAssignment, $total); $this->_store = $quote->getStore(); if (!$this->weeeData->isEnabled($this->_store)) { return $this; @@ -65,13 +68,12 @@ public function collect( $weeeCodeToWeeeTaxDetailsMap[$weeeCode] = $weeeTaxDetails; } } - + $productTaxes = []; //Process each item that has taxable weee foreach ($itemToWeeeCodeMap as $mapping) { $item = $mapping['item']; $this->weeeData->setApplied($item, []); - $productTaxes = []; $totalValueInclTax = 0; $baseTotalValueInclTax = 0; @@ -113,15 +115,17 @@ public function collect( $baseTotalRowValueExclTax += $baseRowValueExclTax; $productTaxes[] = [ - 'title' => $attributeCode, //TODO: fix this - 'base_amount' => $baseValueExclTax, - 'amount' => $valueExclTax, - 'row_amount' => $rowValueExclTax, - 'base_row_amount' => $baseRowValueExclTax, - 'base_amount_incl_tax' => $baseValueInclTax, - 'amount_incl_tax' => $valueInclTax, - 'row_amount_incl_tax' => $rowValueInclTax, - 'base_row_amount_incl_tax' => $baseRowValueInclTax, + [ + 'title' => $attributeCode, //TODO: fix this + 'base_amount' => $baseValueExclTax, + 'amount' => $valueExclTax, + 'row_amount' => $rowValueExclTax, + 'base_row_amount' => $baseRowValueExclTax, + 'base_amount_incl_tax' => $baseValueInclTax, + 'amount_incl_tax' => $valueInclTax, + 'row_amount_incl_tax' => $rowValueInclTax, + 'base_row_amount_incl_tax' => $baseRowValueInclTax, + ], ]; } @@ -143,8 +147,11 @@ public function collect( $baseTotalRowValueInclTax ); - $this->weeeData->setApplied($item, array_merge($this->weeeData->getApplied($item), $productTaxes)); } + $this->weeeData->setApplied( + $item, + array_merge($this->weeeData->getApplied($item), ...$productTaxes) + ); } return $this; } @@ -196,7 +203,7 @@ protected function createItemToWeeeCodeMapping($weeeCodeToItemMap) /** * Process row amount based on FPT total amount configuration setting * - * @param \Magento\Quote\Model\Quote\Address\Total $total + * @param Total $total * @param float $rowValueExclTax * @param float $baseRowValueExclTax * @param float $rowValueInclTax @@ -226,14 +233,13 @@ protected function processTotalAmount( /** * Fetch the Weee total amount for display in totals block when building the initial quote * - * @param \Magento\Quote\Model\Quote $quote - * @param \Magento\Quote\Model\Quote\Address\Total $total + * @param Quote $quote + * @param Total $total * @return array */ - public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total) + public function fetch(Quote $quote, Total $total) { - /** @var $items \Magento\Sales\Model\Order\Item[] */ - $items = isset($total['address_quote_items']) ? $total['address_quote_items'] : []; + $items = $total['quote_items'] ?? []; $weeeTotal = $this->weeeData->getTotalAmounts($items, $quote->getStore()); if ($weeeTotal) { diff --git a/dev/tests/integration/testsuite/Magento/Weee/Model/Total/Quote/CalculateTest.php b/dev/tests/integration/testsuite/Magento/Weee/Model/Total/Quote/CalculateTest.php new file mode 100644 index 0000000000000..97cde94a60abe --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Weee/Model/Total/Quote/CalculateTest.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Weee\Model\Total\Quote; + +use Magento\Checkout\Api\Data\TotalsInformationInterface; +use Magento\Checkout\Model\TotalsInformationManagement; +use Magento\Quote\Model\Quote\Address; +use Magento\Quote\Model\Quote\AddressFactory; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Quote totals calculate tests class + */ +class CalculateTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var TotalsInformationManagement + */ + private $totalsManagement; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = ObjectManager::getInstance(); + $this->totalsManagement = $this->objectManager->get(TotalsInformationManagement::class); + } + + /** + * Multishipping quote with FPT Weee TAX totals calculation test + * + * @magentoDataFixture Magento/Weee/_files/quote_multishipping.php + * @magentoConfigFixture default_store tax/weee/enable 1 + * @magentoConfigFixture default_store tax/weee/apply_vat 1 + */ + public function testGetWeeTaxTotals() + { + /** @var QuoteFactory $quoteFactory */ + $quoteFactory = $this->objectManager->get(QuoteFactory::class); + /** @var QuoteResource $quoteResource */ + $quoteResource = $this->objectManager->get(QuoteResource::class); + $quote = $quoteFactory->create(); + $quoteResource->load($quote, 'multishipping_fpt_quote_id', 'reserved_order_id'); + $cartId = $quote->getId(); + $addressFactory = $this->objectManager->get(AddressFactory::class); + /** @var Address $newAddress */ + $newAddress = $addressFactory->create()->setAddressType('shipping'); + $newAddress->setCountryId('US')->setRegionId(12)->setRegion('California')->setPostcode('90230'); + $addressInformation = $this->objectManager->create( + TotalsInformationInterface::class, + [ + 'data' => [ + 'address' => $newAddress, + 'shipping_method_code' => 'flatrate', + 'shipping_carrier_code' => 'flatrate', + ], + ] + ); + + $actual = $this->totalsManagement->calculate($cartId, $addressInformation); + + $items = $actual->getTotalSegments(); + $this->assertTrue(array_key_exists('weee_tax', $items)); + $this->assertEquals(25.4, $items['weee_tax']->getValue()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping.php b/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping.php new file mode 100644 index 0000000000000..79ed227c2e5fb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Api\Data\AddressInterface; +use Magento\Quote\Api\Data\PaymentInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address\Rate; +use Magento\Quote\Model\Quote\Item; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var CartRepositoryInterface $quoteRepository */ +$quoteRepository = $objectManager->get(CartRepositoryInterface::class); +$store = $storeManager->getStore(); +/** @var Quote $quote */ +$quote = $quoteFactory->create(); +$quote->setReservedOrderId('multishipping_fpt_quote_id') + ->setCustomerEmail('customer001@test.com') + ->setStoreId($storeManager->getStore()->getId()); + +$shipping = [ + 'firstname' => 'Jonh', + 'lastname' => 'Doe', + 'telephone' => '0333-233-221', + 'street' => ['Main Division 1'], + 'city' => 'Culver City', + 'region' => 'CA', + 'postcode' => 90800, + 'country_id' => 'US', + 'email' => 'customer001@shipping.test', + 'address_type' => 'shipping', +]; +$methodCode = 'flatrate_flatrate'; + /** @var Rate $rate */ + $rate = $objectManager->create(Rate::class); + $rate->setCode($methodCode) + ->setPrice(5.00); + + $address = $objectManager->create(AddressInterface::class, ['data' => $shipping]); + $address->setShippingMethod($methodCode) + ->addShippingRate($rate) + ->setShippingAmount(5.00) + ->setBaseShippingAmount(5.00); + + $quote->addAddress($address); + +/** @var AddressInterface $address */ +$address = $objectManager->create( + AddressInterface::class, + [ + 'data' => [ + 'firstname' => 'Jonh', + 'lastname' => 'Doe', + 'telephone' => '0333-233-221', + 'street' => ['Third Division 1'], + 'city' => 'New York', + 'region' => 'NY', + 'postcode' => 10029, + 'country_id' => 'US', + 'email' => 'customer001@billing.test', + 'address_type' => 'billing', + ], + ] +); +$quote->setBillingAddress($address); + +$quote->setIsMultiShipping(1); +$quoteRepository->save($quote); + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +Resolver::getInstance()->requireDataFixture('Magento/Weee/_files/product_with_fpt.php'); +/** @var Product $product */ +$product = $productRepository->get('simple-with-ftp'); + +/** @var Item $item */ +$item = $objectManager->create(Item::class); +$item->setProduct($product) + ->setPrice($product->getPrice()) + ->setQty(2); +$quote->addItem($item); +$quoteRepository->save($quote); + +$addressList = $quote->getAllShippingAddresses(); +$address = reset($addressList); +$item->setQty(2); +$address->setTotalQty(2); +$address->addItem($item); +$quoteRepository->save($quote); + +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'multishipping_fpt_quote_id', 'reserved_order_id'); +/** @var PaymentInterface $payment */ +$payment = $objectManager->create(PaymentInterface::class); +$payment->setMethod('checkmo'); +$quote->setPayment($payment); +$quote->collectTotals(); +$quoteRepository->save($quote); diff --git a/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping_rollback.php b/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping_rollback.php new file mode 100644 index 0000000000000..a5542ca236eba --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Weee/_files/quote_multishipping_rollback.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +/** @var ObjectManager $objectManager */ +$objectManager = Bootstrap::getObjectManager(); + +/** @var SearchCriteriaBuilder $searchCriteriaBuilder */ +$searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class); +$searchCriteria = $searchCriteriaBuilder + ->addFilter('reserved_order_id', 'multishipping_fpt_quote_id') + ->create(); +/** @var CartRepositoryInterface $quoteRepository */ +$quoteRepository = $objectManager->get(CartRepositoryInterface::class); +$quotesList = $quoteRepository->getList($searchCriteria)->getItems(); + +if (!empty($quotesList)) { + $quote = array_pop($quotesList); + $quoteRepository->delete($quote); +} + +Resolver::getInstance()->requireDataFixture('Magento/Weee/_files/product_with_fpt_rollback.php'); From 9bbf81f62e1af44855c2db55fc0c48b43cba0d19 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 8 Jan 2021 16:39:11 +0200 Subject: [PATCH 142/242] MC-40073: Create automated test for: "Guest and customer comparison lists merging" --- .../testsuite/Magento/Catalog/_files/visitor_compare_list.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php index da5089f25e027..8767f030f9367 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/visitor_compare_list.php @@ -14,7 +14,6 @@ Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); $objectManager = Bootstrap::getObjectManager(); - /** @var Visitor $visitor */ $visitor = $objectManager->get(Visitor::class); $visitor->setVisitorId(123); From c13cadaf6534632e49a794151ffe7f81a9017908 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Fri, 8 Jan 2021 16:42:10 +0200 Subject: [PATCH 143/242] MC-35690: [B2B] Unexpected results of editing of a Bundle Product in the Shopping Cart, added from a Requisition List --- .../Catalog/Product/View/Type/BundleTest.php | 15 +++++--- .../Catalog/Product/View/Type/BundleTest.php | 38 ------------------- 2 files changed, 9 insertions(+), 44 deletions(-) diff --git a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php index c929c04ee83f0..9f3d4a908f062 100644 --- a/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php @@ -214,6 +214,8 @@ public function testGetJsonConfigFixedPriceBundleNoOption() public function testGetJsonConfigFixedPriceBundle() { + $optionId = 1; + $optionQty = 2; $baseAmount = 123; $basePriceValue = 123123; $selections = [ @@ -230,7 +232,6 @@ public function testGetJsonConfigFixedPriceBundle() true ) ]; - $bundleProductPrice = $this->getMockBuilder(Price::class) ->disableOriginalConstructor() ->setMethods(['getLowestPrice']) @@ -246,10 +247,8 @@ public function testGetJsonConfigFixedPriceBundle() $this->bundleProductPriceFactory->expects($this->once()) ->method('create') ->willReturn($bundleProductPrice); + $options = [$this->createOption($optionId, 'Title `1', $selections)]; - $options = [ - $this->createOption(1, 'Title `1', $selections), - ]; $finalPriceMock = $this->getPriceMock( [ 'getPriceWithoutOption' => new DataObject( @@ -289,7 +288,10 @@ public function testGetJsonConfigFixedPriceBundle() $preconfiguredValues = new DataObject( [ 'bundle_option' => [ - 1 => 123123111, + $optionId => [123123111], + ], + 'bundle_option_qty' => [ + $optionId => $optionQty, ], ] ); @@ -306,7 +308,8 @@ public function testGetJsonConfigFixedPriceBundle() $this->assertEquals(110, $jsonConfig['prices']['oldPrice']['amount']); $this->assertEquals(100, $jsonConfig['prices']['basePrice']['amount']); $this->assertEquals(100, $jsonConfig['prices']['finalPrice']['amount']); - $this->assertEquals([1], $jsonConfig['positions']); + $this->assertEquals([$optionId], $jsonConfig['positions']); + $this->assertEquals($optionQty, $jsonConfig['options'][$optionId]['selections'][1123]['qty']); } /** 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 a90c971b0fd0e..517109625424c 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 @@ -8,17 +8,14 @@ namespace Magento\Bundle\Block\Catalog\Product\View\Type; use Magento\Bundle\Model\Product\Price; -use Magento\Bundle\Model\Product\Type; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Catalog\Helper\Product as ProductHelper; 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; -use Magento\Framework\DataObject\Factory as DataObjectFactory; /** * Class checks bundle product view behaviour @@ -90,41 +87,6 @@ public function testGetJsonConfig(): void $this->assertEquals(5, $selection['prices']['finalPrice']['amount']); } - /** - * Check that selection qty is calculated correctly for Bundle config. - * - * @return void - */ - public function testGetJsonConfigWithPreconfiguredValues(): void - { - $optionQty = 3; - $bundleProduct = $this->productRepository->get('bundle-product'); - $bundleSelection = $this->productRepository->get('simple'); - - /** @var Type $typeInstance */ - $typeInstance = $bundleProduct->getTypeInstance(); - $typeInstance->setStoreFilter($bundleProduct->getStoreId(), $bundleProduct); - $optionCollection = $typeInstance->getOptionsCollection($bundleProduct); - $optionId = $optionCollection->getFirstItem()->getId(); - $preconfiguredValues = $this->objectManager->get(DataObjectFactory::class)->create([ - 'bundle_option' => [ - $optionId => [$bundleSelection->getId()] - ], - 'bundle_option_qty' => [ - $optionId => $optionQty - ], - ]); - - /** @var ProductHelper $productHelper */ - $productHelper = $this->objectManager->get(ProductHelper::class); - $productHelper->prepareProductOptions($bundleProduct, $preconfiguredValues); - $this->registerProduct($bundleProduct); - - $resultConfig = $this->json->unserialize($this->block->getJsonConfig()); - $this->assertTrue(isset($resultConfig['options'][$optionId]['selections'][$optionId]['qty'])); - $this->assertEquals($optionQty, $resultConfig['options'][$optionId]['selections'][$optionId]['qty']); - } - /** * @dataProvider isSalableForStockStatusProvider * From 940d74adbfe02a5bc5c169285d70dc4f99a739e5 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Fri, 8 Jan 2021 16:58:13 +0200 Subject: [PATCH 144/242] MC-23915: Wrong currency symbol in creditmemo_grid & sales_order_view > creditmemo grid for subtotal & Shipping and Handling fee --- .../Listing/Column/PurchasedPriceTest.php | 144 ++++++++++++------ .../Listing/Column/PurchasedPrice.php | 37 ++++- .../Listing/Column/PurchasedPriceTest.php | 69 +++++++++ 3 files changed, 199 insertions(+), 51 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php index cc1408ecd816e..f0bf116974fa8 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php @@ -8,6 +8,10 @@ namespace Magento\Sales\Test\Unit\Ui\Component\Listing\Column; use Magento\Directory\Model\Currency; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\Data\OrderSearchResultInterface; +use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\Processor; @@ -17,6 +21,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Test for \Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice + */ class PurchasedPriceTest extends TestCase { /** @@ -34,6 +41,21 @@ class PurchasedPriceTest extends TestCase */ private $orderRepository; + /** + * @var SearchCriteria|MockObject + */ + private $searchCriteriaMock; + + /** + * @var OrderSearchResultInterface|MockObject + */ + private $orderSearchResultMock; + + /** + * @var OrderInterface|MockObject + */ + private $order; + protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -47,56 +69,61 @@ protected function setUp(): void ->setMethods(['load', 'format']) ->disableOriginalConstructor() ->getMock(); - $this->orderRepository = $this->getMockBuilder(OrderRepositoryInterface::class) - ->setMethods(['getList','get','delete','save','getOrderCurrencyCode']) - ->disableOriginalConstructor() - ->getMock(); + $this->orderRepository = $this->getMockForAbstractClass(OrderRepositoryInterface::class); + $this->order = $this->getMockForAbstractClass(OrderInterface::class); + $this->orderSearchResultMock = $this->getMockForAbstractClass(OrderSearchResultInterface::class); + $this->searchCriteriaMock = $this->createMock(SearchCriteria::class); + $searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class); + $searchCriteriaBuilderMock->expects($this->once()) + ->method('addFilter') + ->willReturnSelf(); + + $searchCriteriaBuilderMock->expects($this->once()) + ->method('create') + ->willReturn($this->searchCriteriaMock); + $this->model = $objectManager->getObject( PurchasedPrice::class, [ 'currency' => $this->currencyMock, 'context' => $contextMock, - 'order' => $this->orderRepository, + 'orderRepository' => $this->orderRepository, + 'order' => $this->order, + 'searchCriteriaBuilder' => $searchCriteriaBuilderMock, + 'searchCriteria' => $this->searchCriteriaMock, + 'orderSearchResult' => $this->orderSearchResultMock, ] ); } /** - * @param string $itemName - * @param string $oldItemValue - * @param string $newItemValue - * @param string|null $orderCurrencyCode + * @param array $orderData + * @param array $dataSource * @dataProvider prepareDataSourceDataProvider */ - public function testPrepareDataSource( - $itemName, - $oldItemValue, - $newItemValue, - $orderCurrencyCode - ): void { - $dataSource = [ - 'data' => [ - 'items' => [ - [ - $itemName => $oldItemValue, - 'order_currency_code' => $orderCurrencyCode, - 'order_id' => 1, - ] - ] - ] - ]; + public function testPrepareDataSource(array $orderData,array $dataSource): void + { + $oldItemValue = 'oldItemValue'; + $newItemValue = 'newItemValue'; + + $this->orderRepository->expects($this->once()) + ->method('getList') + ->with($this->searchCriteriaMock) + ->willReturn($this->orderSearchResultMock); + + $this->orderSearchResultMock->expects($this->once()) + ->method('getItems') + ->willReturn([$this->order]); + + $this->order->expects($this->once()) + ->method('getEntityId') + ->willReturn($orderData['entity_id']); - if (isset($dataSource['data']['items'][0]['order_currency_code'])) { - $currencyCode = $dataSource['data']['items'][0]['order_currency_code']; - } else { - $currencyCode = 'FR'; - $this->orderRepository->expects($this->once()) - ->method('get') - ->willReturnSelf(); - $this->orderRepository->expects($this->once()) - ->method('getOrderCurrencyCode') - ->willReturn($currencyCode); - } + $this->order->expects($this->once()) + ->method('getOrderCurrencyCode') + ->willReturn($orderData['order_currency_code']); + + $currencyCode = $dataSource['data']['items'][0]['order_currency_code'] ?? $orderData['order_currency_code']; $this->currencyMock->expects($this->once()) ->method('load') @@ -108,9 +135,9 @@ public function testPrepareDataSource( ->with($oldItemValue, [], false) ->willReturn($newItemValue); - $this->model->setData('name', $itemName); + $this->model->setData('name', 'item_name'); $dataSource = $this->model->prepareDataSource($dataSource); - $this->assertEquals($newItemValue, $dataSource['data']['items'][0][$itemName]); + $this->assertEquals($newItemValue, $dataSource['data']['items'][0]['item_name']); } /** @@ -120,17 +147,38 @@ public function prepareDataSourceDataProvider(): array { return [ [ - 'item_name' => 'itemName', - 'old_item_value' => 'oldItemValue', - 'new_item_value' => 'newItemValue', - 'order_currency_code' => 'US', + 'orderData' => [ + 'entity_id' => 1, + 'order_currency_code' => 'US', + ], + 'dataSource' => [ + 'data' => [ + 'items' => [ + [ + 'item_name' => 'oldItemValue', + 'order_currency_code' => 'US', + 'order_id' => 1, + ] + ] + ] + ] ], [ - 'item_name' => 'itemName', - 'old_item_value' => 'oldItemValue', - 'new_item_value' => 'newItemValue', - 'order_currency_code' => null, - ], + 'orderData' => [ + 'entity_id' => 1, + 'order_currency_code' => 'FR', + ], + 'dataSource' => [ + 'data' => [ + 'items' => [ + [ + 'item_name' => 'oldItemValue', + 'order_id' => 1, + ] + ] + ] + ] + ] ]; } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php index fc38d4d010b8c..09e78753634c3 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php @@ -7,6 +7,7 @@ namespace Magento\Sales\Ui\Component\Listing\Column; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Sales\Api\OrderRepositoryInterface; @@ -34,6 +35,11 @@ class PurchasedPrice extends Column */ private $orderRepository; + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + /** * Constructor * @@ -44,6 +50,7 @@ class PurchasedPrice extends Column * @param array $data * @param Currency $currency * @param OrderRepositoryInterface $orderRepository + * @param SearchCriteriaBuilder $searchCriteriaBuilder */ public function __construct( ContextInterface $context, @@ -52,16 +59,20 @@ public function __construct( array $components = [], array $data = [], Currency $currency = null, - OrderRepositoryInterface $orderRepository = null + OrderRepositoryInterface $orderRepository = null, + SearchCriteriaBuilder $searchCriteriaBuilder = null ) { $this->priceFormatter = $priceFormatter; $this->currency = $currency ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(Currency::class); $this->orderRepository = $orderRepository ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(OrderRepositoryInterface::class); + $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: \Magento\Framework\App\ObjectManager::getInstance() + ->create(SearchCriteriaBuilder::class); parent::__construct($context, $uiComponentFactory, $components, $data); } + /** * Prepare Data Source * @@ -71,9 +82,10 @@ public function __construct( public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { + $orderIds = array_column($dataSource['data']['items'],'order_id'); + $orderCurrencyCodes = $this->getOrdersCurrency($orderIds); foreach ($dataSource['data']['items'] as & $item) { - $currencyCode = $item['order_currency_code'] - ?? $this->orderRepository->get($item['order_id'])->getOrderCurrencyCode(); + $currencyCode = $item['order_currency_code'] ?? $orderCurrencyCodes[$item['order_id']]; $purchaseCurrency = $this->currency->load($currencyCode); $item[$this->getData('name')] = $purchaseCurrency ->format($item[$this->getData('name')], [], false); @@ -82,4 +94,23 @@ public function prepareDataSource(array $dataSource) return $dataSource; } + + /** + * @param array $orderIds + * @return array + */ + private function getOrdersCurrency(array $orderIds): array + { + $orderCurrencyCodes = []; + + $searchCriteria = $this->searchCriteriaBuilder + ->addFilter('entity_id', $orderIds ,'in') + ->create(); + + foreach ($this->orderRepository->getList($searchCriteria)->getItems() as $order) { + $orderCurrencyCodes[$order->getEntityId()] = $order->getOrderCurrencyCode(); + } + + return $orderCurrencyCodes; + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php new file mode 100644 index 0000000000000..621fd048bca94 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Ui\Component\Listing\Column; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order; +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Helper\Bootstrap; + +/** + * Test for \Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice + * + * @magentoAppArea adminhtml + */ +class PurchasedPriceTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var PurchasedPrice + */ + private $model; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->create(PurchasedPrice::class, [ + 'data' => [ + 'name' => 'subtotal', + ], + ]); + } + + /** + * Verify prepare data source without order currency code + * + * @magentoDataFixture Magento/Sales/_files/order.php + * @return void + */ + public function testPrepareDataSourceWithoutOrderCurrencyCode(): void + { + $order = $this->objectManager->get(Order::class)->loadByIncrementId('100000001'); + + $dataSource = [ + 'data' => [ + 'items' => [ + [ + 'order_id' => $order->getEntityId(), + 'subtotal' => 100, + ], + ], + ], + ]; + + $result = $this->model->prepareDataSource($dataSource); + $this->assertEquals('$100.00', $result['data']['items'][0]['subtotal']); + } +} From 75825dc0eaf53d0a9652ba7e673a064fd09ff096 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 8 Jan 2021 17:15:32 +0200 Subject: [PATCH 145/242] MC-40073: Create automated test for: "Guest and customer comparison lists merging" --- .../Compare/BindCustomerLoginObserverTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php index c177c902d9d49..f5af965dab02f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Observer/Compare/BindCustomerLoginObserverTest.php @@ -50,6 +50,17 @@ protected function setUp(): void $this->listCompareFactory = $this->objectManager->get(ListCompareFactory::class); } + /** + * @inheritdoc + */ + protected function tearDown(): void + { + $this->session->logout(); + $this->visitor->setId(null); + + parent::tearDown(); + } + /** * @magentoDataFixture Magento/Catalog/_files/visitor_compare_list.php * @magentoDataFixture Magento/Customer/_files/customer.php From 68de5b259060f5840fb97d2dd5b242ceaad97d8c Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Fri, 8 Jan 2021 18:38:24 +0200 Subject: [PATCH 146/242] added AdminClickAddNewPageOnPagesGridActionGroup --- .../Model/Sales/Order/Pdf/Items/Invoice.php | 151 +++++--- .../Sales/Order/Pdf/Items/InvoiceTest.php | 184 ++++++++++ .../Order/Pdf/Items/InvoiceTestProvider.php | 329 ++++++++++++++++++ ...ngeWebSiteAssignedToProductActionGroup.xml | 21 ++ ...inCheckProductOnProductGridActionGroup.xml | 37 +- .../AdminSetPriceForMassUpdateActionGroup.xml | 24 ++ .../AdminSortProductsGridByActionGroup.xml | 22 ++ ...oductPriceUpdatedOnEditPageActionGroup.xml | 25 ++ .../AddOutOfStockProductToCompareListTest.xml | 2 +- .../AdminAddInStockProductToTheCartTest.xml | 5 +- ...tomAttributeValuesAfterProductSaveTest.xml | 4 +- .../Test/AdminMassProductPriceUpdateTest.xml | 76 ++-- ...edFieldsHaveRequiredFieldIndicatorTest.xml | 2 +- .../AdminSimpleProductImagesTest.xml | 4 +- .../Mftf/Test/AdminSortingByWebsitesTest.xml | 39 +-- ...dateFlatCategoryNameAndDescriptionTest.xml | 11 +- ...dminUpdateSimpleProductTieredPriceTest.xml | 5 +- ...ceInStockVisibleInCatalogAndSearchTest.xml | 5 +- ...arPriceInStockVisibleInCatalogOnlyTest.xml | 5 +- .../Test/CheckTierPricingOfProductsTest.xml | 5 +- .../CreateProductAttributeEntityDateTest.xml | 6 +- .../EndToEndB2CGuestUserTest.xml | 5 +- ...vailableAfterEnablingSubCategoriesTest.xml | 2 +- ...tProductsDisplayUsingElasticSearchTest.xml | 4 +- ...oreFrontRecentlyViewedAtStoreLevelTest.xml | 4 +- ...rontRecentlyViewedAtStoreViewLevelTest.xml | 4 +- ...heckDefaultNumberProductsToDisplayTest.xml | 5 +- ...refrontProductNameWithHTMLEntitiesTest.xml | 4 +- ...ctAndProductCategoryPartialReindexTest.xml | 4 +- ...ssertStorefrontCartDiscountActionGroup.xml | 21 ++ ...ndleDynamicProductFromShoppingCartTest.xml | 2 +- ...BundleFixedProductFromShoppingCartTest.xml | 2 +- ...OnePageCheckoutWithAllProductTypesTest.xml | 2 +- ...frontCheckoutDisabledBundleProductTest.xml | 2 +- ...tCheckoutWithCouponAndZeroSubtotalTest.xml | 6 +- ...efrontUKCustomerCheckoutWithCouponTest.xml | 6 +- ...nClickAddNewPageOnPagesGridActionGroup.xml | 19 + ...yTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml | 2 +- app/code/Magento/Csp/etc/config.xml | 12 + .../Component/Listing/Column/Confirmation.php | 34 +- ...dableProductLinkAfterPartialRefundTest.xml | 4 +- ...chaseFunctionalityNegativeScenarioTest.xml | 2 +- ...efrontInstantPurchaseFunctionalityTest.xml | 2 +- .../MessageQueue/Model/ResourceModel/Lock.php | 48 +-- app/code/Magento/PageCache/etc/varnish6.vcl | 6 +- .../Block/Adminhtml/Order/Totals/Tax.php | 2 +- .../Magento/Sales/Model/AdminOrder/Create.php | 7 +- .../Magento/Sales/Model/Order/Invoice.php | 5 + ...kRefundOfflineOnNewMemoPageActionGroup.xml | 19 + ...reateCreditMemoBankTransferPaymentTest.xml | 4 +- ...AdminCreateCreditMemoPartialRefundTest.xml | 4 +- ...nCreateCreditMemoWithPurchaseOrderTest.xml | 4 +- .../Test/Mftf/Test/AdminCreateInvoiceTest.xml | 7 +- .../Test/Mftf/Test/AdminInvoiceOrderTest.xml | 66 ++++ .../Test/Mftf/Test/EndToEndB2CAdminTest.xml | 4 +- .../Block/Adminhtml/Order/Totals/TaxTest.php | 154 +++++--- ...eConditionAndFreeShippingIsAppliedTest.xml | 4 +- ...inCreateCartPriceRuleEmptyFromDateTest.xml | 6 +- ...inCreateCartPriceRuleForCouponCodeTest.xml | 6 +- ...ateCartPriceRuleForGeneratedCouponTest.xml | 6 +- ...talAndVerifyRuleConditionIsAppliedTest.xml | 4 +- ...oryAndVerifyRuleConditionIsAppliedTest.xml | 4 +- ...ghtAndVerifyRuleConditionIsAppliedTest.xml | 4 +- .../StorefrontCartPriceRuleCountryTest.xml | 6 +- .../StorefrontCartPriceRulePostcodeTest.xml | 6 +- .../StorefrontCartPriceRuleQuantityTest.xml | 6 +- .../Test/StorefrontCartPriceRuleStateTest.xml | 6 +- .../StorefrontCartPriceRuleSubtotalTest.xml | 6 +- ...ValueWithFullDiscountUsingCartRuleTest.xml | 6 +- .../base/web/js/dynamic-rows/dynamic-rows.js | 18 +- .../Mftf/Test/NewProductsListWidgetTest.xml | 2 +- .../Test/Mftf/Test/ProductsListWidgetTest.xml | 2 +- .../Catalog/Api/CategoryRepositoryTest.php | 39 ++- .../Api/ProductWebsiteLinkRepositoryTest.php | 109 ++++++ .../TestModuleMysqlMq/Model/Processor.php | 25 +- .../TestModuleMysqlMq/etc/communication.xml | 1 + .../Magento/TestModuleMysqlMq/etc/queue.xml | 3 + .../TestModuleMysqlMq/etc/queue_consumer.xml | 1 + .../TestModuleMysqlMq/etc/queue_publisher.xml | 3 + .../TestModuleMysqlMq/etc/queue_topology.xml | 1 + .../Product/Edit/Tab/Alerts/StockTest.php | 90 +++++ .../Product/View/Options/Type/DateTest.php | 9 +- .../Product/Attribute/Backend/StockTest.php | 62 ++++ .../Product/Attribute/RepositoryTest.php | 146 ++++++++ .../ProductWebsiteLinkRepositoryTest.php | 87 +++++ .../Catalog/Url/Rewrite/SuffixTest.php | 287 +++++++++++++++ .../Product/Form/Modifier/AlertsTest.php | 56 +++ .../Model/Config/Backend/BackordersTest.php | 99 ++++++ .../AddQuantityFilterToCollectionTest.php | 133 +++++++ .../Model/Collector/ConfigCollectorTest.php | 4 +- .../Listing/Column/ConfirmationTest.php | 127 +++++++ .../MessageQueue/Model/ConsumerTest.php | 109 ++++++ .../Model/ResourceModel/LockTest.php | 28 ++ .../_files/product_alert_rollback.php | 33 ++ .../_files/stock_alert_on_second_website.php | 66 ++++ ...stock_alert_on_second_website_rollback.php | 52 +++ .../Adminhtml/Order/Create/LoadBlockTest.php | 34 ++ .../Magento/Sales/Model/Order/InvoiceTest.php | 69 +++- .../Configurable/Listing/ConfigurableTest.php | 104 ++++++ .../Product/Renderer/ConfigurableTest.php | 40 ++- .../configurable_product_with_images.php | 41 +++ ...figurable_product_with_images_rollback.php | 15 + .../base/js/dynamic-rows/dynamic-rows.test.js | 33 ++ .../Magento/Framework/Filesystem/Io/Ftp.php | 3 +- .../Stdlib/Cookie/PhpCookieManager.php | 5 +- .../Test/Unit/Cookie/PhpCookieManagerTest.php | 5 +- setup/performance-toolkit/config/di.xml | 2 + .../Mail/Template/TransportBuilderMock.php | 28 ++ .../Framework/Mail/TransportInterfaceMock.php | 45 +++ 109 files changed, 3178 insertions(+), 348 deletions(-) create mode 100644 app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php create mode 100644 app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickAddNewPageOnPagesGridActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml create mode 100644 dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php create mode 100644 dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php create mode 100644 dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php create mode 100644 setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php create mode 100644 setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php index 64e9f56dd65bc..a7f0a70b45219 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php @@ -8,6 +8,7 @@ namespace Magento\Bundle\Model\Sales\Order\Pdf\Items; use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\DataObject; use Magento\Framework\Filesystem; use Magento\Framework\Filter\FilterManager; use Magento\Framework\Model\Context; @@ -69,34 +70,38 @@ public function __construct( } /** - * Draw item line + * Draw bundle product item line * * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function draw() { - $order = $this->getOrder(); - $item = $this->getItem(); - $pdf = $this->getPdf(); - $page = $this->getPage(); + $draw = $this->drawChildrenItems(); + $draw = $this->drawCustomOptions($draw); + $page = $this->getPdf()->drawLineBlocks($this->getPage(), $draw, ['table_header' => true]); + + $this->setPage($page); + } + + /** + * Draw bundle product children items + * + * @return array + */ + private function drawChildrenItems(): array + { $this->_setFontRegular(); - $items = $this->getChildren($item); $prevOptionId = ''; $drawItems = []; - - foreach ($items as $childItem) { - $line = []; - + $optionId = 0; + $lines = []; + foreach ($this->getChildren($this->getItem()) as $childItem) { + $index = array_key_last($lines) !== null ? array_key_last($lines) + 1 : 0; $attributes = $this->getSelectionAttributes($childItem); if (is_array($attributes)) { $optionId = $attributes['option_id']; - } else { - $optionId = 0; } if (!isset($drawItems[$optionId])) { @@ -104,15 +109,13 @@ public function draw() } if ($childItem->getOrderItem()->getParentItem() && $prevOptionId != $attributes['option_id']) { - $line[0] = [ + $lines[$index][] = [ 'font' => 'italic', 'text' => $this->string->split($attributes['option_label'], 45, true, true), 'feed' => 35, ]; - $drawItems[$optionId] = ['lines' => [$line], 'height' => 15]; - - $line = []; + $index++; $prevOptionId = $attributes['option_id']; } @@ -124,35 +127,97 @@ public function draw() $feed = 35; $name = $childItem->getName(); } - $line[] = ['text' => $this->string->split($name, 35, true, true), 'feed' => $feed]; + $lines[$index][] = ['text' => $this->string->split($name, 35, true, true), 'feed' => $feed]; - // draw SKUs - if (!$childItem->getOrderItem()->getParentItem()) { - $text = []; - foreach ($this->string->split($item->getSku(), 17) as $part) { - $text[] = $part; - } - $line[] = ['text' => $text, 'feed' => 255]; - } + $lines = $this->drawSkus($childItem, $lines); - // draw prices - if ($this->canShowPriceInfo($childItem)) { - $price = $order->formatPriceTxt($childItem->getPrice()); - $line[] = ['text' => $price, 'feed' => 395, 'font' => 'bold', 'align' => 'right']; - $line[] = ['text' => $childItem->getQty() * 1, 'feed' => 435, 'font' => 'bold']; + $lines = $this->drawPrices($childItem, $lines); + } + $drawItems[$optionId]['lines'] = $lines; - $tax = $order->formatPriceTxt($childItem->getTaxAmount()); - $line[] = ['text' => $tax, 'feed' => 495, 'font' => 'bold', 'align' => 'right']; + return $drawItems; + } - $row_total = $order->formatPriceTxt($childItem->getRowTotal()); - $line[] = ['text' => $row_total, 'feed' => 565, 'font' => 'bold', 'align' => 'right']; + /** + * Draw sku parts + * + * @param DataObject $childItem + * @param array $lines + * @return array + */ + private function drawSkus(DataObject $childItem, array $lines): array + { + $index = array_key_last($lines); + if (!$childItem->getOrderItem()->getParentItem()) { + $text = []; + foreach ($this->string->split($this->getItem()->getSku(), 17) as $part) { + $text[] = $part; } + $lines[$index][] = ['text' => $text, 'feed' => 255]; + } + + return $lines; + } - $drawItems[$optionId]['lines'][] = $line; + /** + * Draw prices for bundle product children items + * + * @param DataObject $childItem + * @param array $lines + * @return array + */ + private function drawPrices(DataObject $childItem, array $lines): array + { + $index = array_key_last($lines); + if ($this->canShowPriceInfo($childItem)) { + $lines[$index][] = ['text' => $childItem->getQty() * 1, 'feed' => 435, 'align' => 'right']; + + $tax = $this->getOrder()->formatPriceTxt($childItem->getTaxAmount()); + $lines[$index][] = ['text' => $tax, 'feed' => 495, 'font' => 'bold', 'align' => 'right']; + + $item = $this->getItem(); + $this->_item = $childItem; + $feedPrice = 380; + $feedSubtotal = $feedPrice + 185; + foreach ($this->getItemPricesForDisplay() as $priceData) { + if (isset($priceData['label'])) { + // draw Price label + $lines[$index][] = ['text' => $priceData['label'], 'feed' => $feedPrice, 'align' => 'right']; + // draw Subtotal label + $lines[$index][] = ['text' => $priceData['label'], 'feed' => $feedSubtotal, 'align' => 'right']; + $index++; + } + // draw Price + $lines[$index][] = [ + 'text' => $priceData['price'], + 'feed' => $feedPrice, + 'font' => 'bold', + 'align' => 'right', + ]; + // draw Subtotal + $lines[$index][] = [ + 'text' => $priceData['subtotal'], + 'feed' => $feedSubtotal, + 'font' => 'bold', + 'align' => 'right', + ]; + $index++; + } + $this->_item = $item; } - // custom options - $options = $item->getOrderItem()->getProductOptions(); + return $lines; + } + + /** + * Draw bundle product custom options + * + * @param array $draw + * @return array + */ + private function drawCustomOptions(array $draw): array + { + $options = $this->getItem()->getOrderItem()->getProductOptions(); if ($options && isset($options['options'])) { foreach ($options['options'] as $option) { $lines = []; @@ -180,12 +245,10 @@ public function draw() $lines[][] = ['text' => $text, 'feed' => 40]; } - $drawItems[] = ['lines' => $lines, 'height' => 15]; + $draw[] = ['lines' => $lines, 'height' => 15]; } } - $page = $pdf->drawLineBlocks($page, $drawItems, ['table_header' => true]); - - $this->setPage($page); + return $draw; } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php new file mode 100644 index 0000000000000..e5bf94241dbd9 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTest.php @@ -0,0 +1,184 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items; + +use Magento\Bundle\Model\Sales\Order\Pdf\Items\Invoice; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\DataObject; +use Magento\Framework\Filesystem; +use Magento\Framework\Filter\FilterManager; +use Magento\Framework\Model\Context; +use Magento\Framework\Model\ResourceModel\AbstractResource; +use Magento\Framework\Registry; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\Stdlib\StringUtils; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Pdf\Invoice as InvoicePdf; +use Magento\Tax\Helper\Data; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Zend_Pdf_Page; + +/** + * Covers bundle order item invoice print logic + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class InvoiceTest extends TestCase +{ + /** + * @var Invoice|MockObject + */ + private $model; + + /** + * @var Data|MockObject + */ + private $taxDataMock; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $contextMock = $this->createMock(Context::class); + $registryMock = $this->createMock(Registry::class); + $this->taxDataMock = $this->createMock(Data::class); + $directoryMock = $this->createMock(Filesystem\Directory\Read::class); + $directoryMock->expects($this->any())->method('getAbsolutePath')->willReturn(''); + $filesystemMock = $this->createMock(Filesystem::class); + $filesystemMock->expects($this->any())->method('getDirectoryRead')->willReturn($directoryMock); + $filterManagerMock = $this->createMock(FilterManager::class); + $stringUtilsMock = $this->createMock(StringUtils::class); + $stringUtilsMock->expects($this->any())->method('split')->willReturnArgument(0); + $resourceMock = $this->createMock(AbstractResource::class); + $collectionMock = $this->createMock(AbstractDb::class); + $serializerMock = $this->createMock(Json::class); + + $this->model = $this->getMockBuilder(Invoice::class) + ->setConstructorArgs( + [ + $contextMock, + $registryMock, + $this->taxDataMock, + $filesystemMock, + $filterManagerMock, + $stringUtilsMock, + $serializerMock, + $resourceMock, + $collectionMock, + [], + ] + ) + ->onlyMethods( + [ + '_setFontRegular', + 'getChildren', + 'isShipmentSeparately', + 'isChildCalculated', + 'getValueHtml', + 'getSelectionAttributes', + ] + ) + ->getMock(); + } + + /** + * @dataProvider \Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items\InvoiceTestProvider::getData + * @param array $expected + * @param string $method + */ + public function testDrawPrice(array $expected, string $method): void + { + $this->taxDataMock->expects($this->any())->method($method)->willReturn(true); + $pageMock = $this->createMock(Zend_Pdf_Page::class); + $this->model->setPage($pageMock); + $pdfMock = $this->createMock(InvoicePdf::class); + $pdfMock->expects($this->any())->method('drawLineBlocks')->with( + $pageMock, + $expected, + ['table_header' => true] + )->willReturn($pageMock); + $this->model->setPdf($pdfMock); + + $this->prepareModel(); + $this->model->draw(); + } + + /** + * Prepare invoice draw model for test execution + * + * @return void + */ + private function prepareModel(): void + { + $parentItem = new DataObject( + [ + 'sku' => 'bundle-simple', + 'name' => 'Bundle', + 'order_item' => new DataObject( + [ + 'product_options' => [], + ] + ), + ] + ); + $items = [ + new DataObject( + [ + 'name' => 'Simple1', + 'sku' => 'simple1', + 'price' => '10.00', + 'price_incl_tax' => '10.83', + 'row_total' => '20.00', + 'row_total_incl_tax' => '21.66', + 'qty' => '2', + 'tax_amount' => '1.66', + 'order_item' => new DataObject( + [ + 'parent_item' => $parentItem, + ] + ), + ] + ), + new DataObject( + [ + 'name' => 'Simple2', + 'sku' => 'simple2', + 'price' => '5.00', + 'price_incl_tax' => '5.41', + 'row_total' => '10.00', + 'row_total_incl_tax' => '10.83', + 'qty' => '2', + 'tax_amount' => '0.83', + 'order_item' => new DataObject( + [ + 'parent_item' => $parentItem, + ] + ), + ] + ), + ]; + $orderMock = $this->createMock(Order::class); + + $this->model->expects($this->any())->method('getChildren')->willReturn($items); + $this->model->expects($this->any())->method('isShipmentSeparately')->willReturn(false); + $this->model->expects($this->any())->method('isChildCalculated')->willReturn(true); + $this->model->expects($this->at(2))->method('getSelectionAttributes')->willReturn( + ['option_id' => 1, 'option_label' => 'test option'] + ); + $this->model->expects($this->at(3))->method('getValueHtml')->willReturn($items[0]->getName()); + $this->model->expects($this->at(5))->method('getSelectionAttributes')->willReturn( + ['option_id' => 1, 'option_label' => 'second option'] + ); + $this->model->expects($this->at(6))->method('getValueHtml')->willReturn($items[1]->getName()); + + $orderMock->expects($this->any())->method('formatPriceTxt')->willReturnArgument(0); + $this->model->setOrder($orderMock); + $this->model->setItem($parentItem); + } +} diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php new file mode 100644 index 0000000000000..7de3d383d006e --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Model/Sales/Order/Pdf/Items/InvoiceTestProvider.php @@ -0,0 +1,329 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Bundle\Test\Unit\Model\Sales\Order\Pdf\Items; + +/** + * Data provider class for InvoiceTest class + */ +class InvoiceTestProvider +{ + /** + * Returns invoice test variations data + * + * @return array[] + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function getData(): array + { + return [ + 'display_both' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Incl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Incl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Excl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '5.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Incl. Tax:', + 'feed' => 380, + 'align' => 'right', + ], + [ + 'text' => 'Incl. Tax:', + 'feed' => 565, + 'align' => 'right', + ], + ], + [ + [ + 'text' => '5.41', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesBothPrices', + ], + 'including_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '21.66', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '5.41', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.83', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceInclTax', + ], + 'excluding_tax' => [ + 'expected' => [ + 1 => [ + 'height' => 15, + 'lines' => [ + [ + [ + 'text' => 'test option', + 'feed' => 35, + 'font' => 'italic', + + ], + ], + [ + [ + 'text' => 'Simple1', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 1.66, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '20.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + [ + [ + 'text' => 'Simple2', + 'feed' => 40, + ], + [ + 'text' => 2, + 'feed' => 435, + 'align' => 'right', + ], + [ + 'text' => 0.83, + 'feed' => 495, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '5.00', + 'feed' => 380, + 'font' => 'bold', + 'align' => 'right', + ], + [ + 'text' => '10.00', + 'feed' => 565, + 'font' => 'bold', + 'align' => 'right', + ], + ], + ], + ], + ], + 'tax_mock_method' => 'displaySalesPriceExclTax', + ], + ]; + } +} diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.xml new file mode 100644 index 0000000000000..76a0af8f63fd5 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminChangeWebSiteAssignedToProductActionGroup.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="AdminChangeWebSiteAssignedToProductActionGroup" extends="AddWebsiteToProductActionGroup"> + <annotations> + <description>Extends AddWebsiteToProductActionGroup. Changes website assigned to product from websiteToDeselect to website</description> + </annotations> + <arguments> + <argument name="websiteToDeselect" type="string"/> + </arguments> + + <uncheckOption selector="{{ProductInWebsitesSection.website(websiteToDeselect)}}" stepKey="uncheckWebsite" after="checkWebsite"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml index 64fab5575e392..8cb737f50c620 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminCheckProductOnProductGridActionGroup.xml @@ -1,22 +1,21 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> +<?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="AdminCheckProductOnProductGridActionGroup"> - <annotations> - <description>Check the checkbox for the product on the Product Grid</description> - </annotations> - <arguments> - <argument name="product" type="entity"/> - </arguments> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCheckProductOnProductGridActionGroup"> + <annotations> + <description>Check the checkbox for the product on the Product Grid</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + </arguments> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> + <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku(product.sku)}}" stepKey="selectProduct"/> - </actionGroup> -</actionGroups> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.xml new file mode 100644 index 0000000000000..b00f181c92360 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSetPriceForMassUpdateActionGroup.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="AdminSetPriceForMassUpdateActionGroup"> + <annotations> + <description>Click the "Change" checkbox for the "Price" field. Set new price.</description> + </annotations> + <arguments> + <argument name="price" type="string"/> + </arguments> + + <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> + <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> + <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="{{price}}"/> + + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.xml new file mode 100644 index 0000000000000..92c714c2478b0 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminSortProductsGridByActionGroup.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="AdminSortProductsGridByActionGroup"> + <annotations> + <description>Sorts the Product Grid by field</description> + </annotations> + <arguments> + <argument name="field" type="string"/> + </arguments> + + <click selector="{{AdminProductGridSection.columnHeader(field)}}" stepKey="clickWebsitesHeaderToSort"/> + <waitForLoadingMaskToDisappear stepKey="waitForApplyingChanges"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.xml new file mode 100644 index 0000000000000..c7a665119b328 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminProductPriceUpdatedOnEditPageActionGroup.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="AssertAdminProductPriceUpdatedOnEditPageActionGroup" extends="OpenEditProductOnBackendActionGroup"> + <annotations> + <description>Validate if Product price is updated on the Product creation/edit page</description> + </annotations> + <arguments> + <argument name="product" type="entity"/> + <argument name="price" type="string"/> + </arguments> + + <waitForPageLoad stepKey="waitForProductToLoad"/> + <seeInField selector="{{AdminProductFormSection.productName}}" userInput="{{product.name}}" stepKey="seeProductName"/> + <seeInField selector="{{AdminProductFormSection.productSku}}" userInput="{{product.sku}}" stepKey="seeProductSku"/> + <seeInField selector="{{AdminProductFormSection.productPrice}}" userInput="{{price}}" stepKey="seeProductPrice"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index 995fa4c7e5977..e1499a2484353 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -56,7 +56,7 @@ <comment userInput="Clear cache and reindex | Comment is kept to preserve the step key for backward compatibility" stepKey="cleanCache"/> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="catalog_product_price"/> </actionGroup> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml index 94d3b46aaa5f1..73019bb5ec0e0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml @@ -58,10 +58,7 @@ <actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickOnDoneButton"/> <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickOnSaveButton"/> <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the product." stepKey="messageYouSavedTheProductIsShown"/> - <!--Clear cache and reindex--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml index 0bdf19c9b8950..ca0616213c593 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckCustomAttributeValuesAfterProductSaveTest.xml @@ -33,9 +33,7 @@ </createData> <!-- Create simple product --> <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindexCatalogSearch"> - <argument name="indices" value="catalogsearch_fulltext"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindexCatalogSearch"/> <!-- Login to Admin page --> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> </before> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml index 070c07d9feb7d..8a5da6d6e3640 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminMassProductPriceUpdateTest.xml @@ -29,52 +29,60 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <!--Open Product Index Page--> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndex"/> - <!--Search products using keyword --> - <actionGroup ref="SearchProductGridByKeyword2ActionGroup" stepKey="searchByKeyword"> - <argument name="keyword" value="Testp"/> - </actionGroup> + <actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="searchByKeyword"/> - <!--Sort Products by ID in descending order--> <actionGroup ref="SortProductsByIdDescendingActionGroup" stepKey="sortProductsByIdDescending"/> - <!--Select products--> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku($$simpleProduct1.sku$$)}}" stepKey="selectFirstProduct"/> - <checkOption selector="{{AdminProductGridSection.productRowCheckboxBySku($$simpleProduct2.sku$$)}}" stepKey="selectSecondProduct"/> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectFirstProduct"> + <argument name="product" value="$simpleProduct1$"/> + </actionGroup> + <actionGroup ref="AdminCheckProductOnProductGridActionGroup" stepKey="selectSecondProduct"> + <argument name="product" value="$simpleProduct2$"/> + </actionGroup> + + <actionGroup ref="AdminClickMassUpdateProductAttributesActionGroup" stepKey="clickDropdown"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickChangeStatus"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForProductAttributePageToLoad"/> - <!-- Update product price--> - <click selector="{{AdminProductGridSection.bulkActionDropdown}}" stepKey="clickDropdown"/> - <click selector="{{AdminProductGridSection.bulkActionOption('Update attributes')}}" stepKey="clickChangeStatus"/> - <waitForPageLoad stepKey="waitForProductAttributePageToLoad"/> - <scrollTo stepKey="scrollToPriceCheckBox" selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" x="0" y="-160"/> - <click selector="{{AdminEditProductAttributesSection.ChangeAttributePriceToggle}}" stepKey="selectPriceCheckBox"/> - <fillField stepKey="fillPrice" selector="{{AdminEditProductAttributesSection.AttributePrice}}" userInput="90.99"/> - <click stepKey="clickOnSaveButton" selector="{{AdminEditProductAttributesSection.Save}}"/> - <waitForPageLoad stepKey="waitForUpdatedProductToSave" /> - <see selector="{{AdminProductMessagesSection.successMessage}}" userInput="Message is added to queue" stepKey="seeAttributeUpateSuccessMsg"/> + <actionGroup ref="AdminSetPriceForMassUpdateActionGroup" stepKey="scrollToPriceCheckBox"> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectPriceCheckBox"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="fillPrice"/> + + <actionGroup ref="AdminSaveProductsMassAttributesUpdateActionGroup" stepKey="clickOnSaveButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForUpdatedProductToSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeAttributeUpateSuccessMsg"/> - <!-- Start message queue --> <actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueueConsumer"> <argument name="consumerName" value="{{AdminProductAttributeUpdateConsumerData.consumerName}}"/> <argument name="maxMessages" value="{{AdminProductAttributeUpdateConsumerData.messageLimit}}"/> </actionGroup> - <!-- Run cron --> + <magentoCLI command="cron:run --group=index" stepKey="runCron"/> - <!--Verify product name, sku and updated price--> - <click stepKey="openFirstProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct1.sku$$)}}"/> - <waitForPageLoad stepKey="waitForFirstProductToLoad"/> - <seeInField stepKey="seeFirstProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct1.name$$"/> - <seeInField stepKey="seeFirstProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct1.sku$$"/> - <seeInField stepKey="seeFirstProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> - <click stepKey="clickOnBackButton" selector="{{AdminGridMainControls.back}}"/> - <waitForPageLoad stepKey="waitForProductsToLoad"/> - <click stepKey="openSecondProduct" selector="{{AdminProductGridSection.productRowBySku($$simpleProduct2.sku$$)}}"/> - <waitForPageLoad stepKey="waitForSecondProductToLoad"/> - <seeInField stepKey="seeSecondProductNameInField" selector="{{AdminProductFormSection.productName}}" userInput="$$simpleProduct2.name$$"/> - <seeInField stepKey="seeSecondProductSkuInField" selector="{{AdminProductFormSection.productSku}}" userInput="$$simpleProduct2.sku$$"/> - <seeInField stepKey="seeSecondProductPriceInField" selector="{{AdminProductFormSection.productPrice}}" userInput="90.99"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openFirstProduct"/> + <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForFirstProductToLoad"> + <argument name="product" value="$$simpleProduct1$$"/> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeFirstProductPriceInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickOnBackButton"/> + + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="waitForProductsToLoad"/> + + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="openSecondProduct"/> + <actionGroup ref="AssertAdminProductPriceUpdatedOnEditPageActionGroup" stepKey="waitForSecondProductToLoad"> + <argument name="product" value="$$simpleProduct2$$"/> + <argument name="price" value="90.99"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductNameInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductSkuInField"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSecondProductPriceInField"/> + </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml index dfe83338c7b6f..b2ed7b9628f38 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminRequiredFieldsHaveRequiredFieldIndicatorTest.xml @@ -60,7 +60,7 @@ <!-- Verify that the CMS page have the required field name indicator next to Page Title --> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnPagePagesGrid"/> <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPage"/> + <actionGroup ref="AdminClickAddNewPageOnPagesGridActionGroup" stepKey="clickAddNewPage"/> <executeJS function="{{CmsNewPagePageBasicFieldsSection.RequiredFieldIndicator}}" stepKey="pageTitleRequiredFieldIndicator"/> <assertEquals message="pass" stepKey="assertRequiredFieldIndicator5"> <actualResult type="variable">pageTitleRequiredFieldIndicator</actualResult> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml index de116b26d1414..8a33f6132aeb9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductImagesTest.xml @@ -141,9 +141,7 @@ <!-- Save the second product --> <click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="saveProduct2"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml index f5046faf82b6f..a9f8eab9a582f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSortingByWebsitesTest.xml @@ -25,7 +25,7 @@ </createData> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <!--Create new website --> + <actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createAdditionalWebsite"> <argument name="newWebsiteName" value="{{customWebsite.name}}"/> <argument name="websiteCode" value="{{customWebsite.code}}"/> @@ -52,31 +52,30 @@ <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> - <!--Assign Custom Website to Simple Product --> - <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToCatalogProductGrid"/> - - <conditionalClick selector="{{AdminProductGridFilterSection.clearFilters}}" dependentSelector="{{AdminProductGridFilterSection.clearFilters}}" visible="true" stepKey="clickClearFiltersInitial"/> + <actionGroup ref="AdminClearFiltersActionGroup" stepKey="navigateToCatalogProductGrid"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickClearFiltersInitial"/> <actionGroup ref="OpenEditProductOnBackendActionGroup" stepKey="assignCustomWebsiteToProduct"> <argument name="product" value="$$productAssignedToCustomWebsite$$"/> </actionGroup> - <scrollTo selector="{{ProductInWebsitesSection.sectionHeader}}" stepKey="scrollToWebsites"/> - <conditionalClick selector="{{ProductInWebsitesSection.sectionHeader}}" dependentSelector="{{AdminProductContentSection.sectionHeaderShow}}" visible="false" stepKey="expandSection"/> - <waitForPageLoad stepKey="waitForPageOpened"/> - <uncheckOption selector="{{ProductInWebsitesSection.website(_defaultWebsite.name)}}" stepKey="deselectMainWebsite"/> - <checkOption selector="{{ProductInWebsitesSection.website(customWebsite.name)}}" stepKey="selectWebsite"/> - - <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickSave"/> - <seeElement selector="{{AdminProductMessagesSection.successMessage}}" stepKey="seeSaveProductMessageAgain"/> + <actionGroup ref="AdminChangeWebSiteAssignedToProductActionGroup" stepKey="scrollToWebsites"> + <argument name="website" value="{{customWebsite.name}}"/> + <argument name="websiteToDeselect" value="{{_defaultWebsite.name}}"/> + </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="expandSection"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageOpened"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="deselectMainWebsite"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="selectWebsite"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickSave"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeSaveProductMessageAgain"/> - <!--Navigate To Product Grid To Check Website Sorting--> <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToCatalogProductGridToSortByWebsite"/> - - <!--Sorting works (By Websites) ASC--> - <click selector="{{AdminProductGridSection.columnHeader('Websites')}}" stepKey="clickWebsitesHeaderToSortAsc"/> + <actionGroup ref="AdminSortProductsGridByActionGroup" stepKey="clickWebsitesHeaderToSortAsc"> + <argument name="field" value="Websites"/> + </actionGroup> <see selector="{{AdminProductGridSection.productGridContentsOnRow('1')}}" userInput="Main Website" stepKey="checkIfProduct1WebsitesAsc"/> - - <!--Sorting works (By Websites) DESC--> - <click selector="{{AdminProductGridSection.columnHeader('Websites')}}" stepKey="clickWebsitesHeaderToSortDesc"/> + <actionGroup ref="AdminSortProductsGridByActionGroup" stepKey="clickWebsitesHeaderToSortDesc"> + <argument name="field" value="Websites"/> + </actionGroup> <see selector="{{AdminProductGridSection.productGridContentsOnRow('1')}}" userInput="{{customWebsite.name}}" stepKey="checkIfProduct1WebsitesDesc"/> </test> </tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml index 27a834833ed76..2124efed31293 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateFlatCategoryNameAndDescriptionTest.xml @@ -34,10 +34,7 @@ <magentoCLI stepKey="setFlatCatalogCategory" command="config:set catalog/frontend/flat_catalog_category 1"/> <!--Open Index Management Page and Select Index mode "Update by Schedule" --> <magentoCLI stepKey="setIndexerMode" command="indexer:set-mode" arguments="schedule" /> - <!--Run full reindex and clear caches --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> @@ -45,9 +42,7 @@ <after> <magentoCLI stepKey="setFlatCatalogCategory" command="config:set catalog/frontend/flat_catalog_category 0 "/> <magentoCLI stepKey="setIndexerMode" command="indexer:set-mode" arguments="realtime" /> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="indexerReindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="indexerReindex"/> <deleteData stepKey="deleteCategory" createDataKey="createCategory" /> <actionGroup ref="AdminDeleteStoreViewActionGroup" stepKey="deleteStoreViewEn"> <argument name="customStore" value="customStoreEN"/> @@ -71,7 +66,7 @@ <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="seeSuccessMessage"/> <!--Run full reindex and clear caches --> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="catalog_category_flat"/> </actionGroup> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index 53d9beb6169ee..420a0604f0382 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -26,10 +26,7 @@ </createData> <createData entity="SimpleSubCategory" stepKey="categoryEntity"/> - <!--TODO: REMOVE AFTER FIX MC-21717 --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value="full_page"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index c5f6e70be046c..9cb326ca6d804 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -95,10 +95,7 @@ <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice245InStock.urlKey}}" stepKey="seeUrlKey"/> - <!--Run re-index task --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Verify customer see updated simple product link on category page --> <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index c3f7240537293..38c0a7449210c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -95,10 +95,7 @@ <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32501InStock.urlKey}}" stepKey="seeUrlKey"/> - <!--Run re-index task --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Verify customer see updated simple product link on category page --> <amOnPage url="{{StorefrontCategoryPage.url($$categoryEntity.name$$)}}" stepKey="openCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml index 5f7e9c4225c00..2095d56ce6c59 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CheckTierPricingOfProductsTest.xml @@ -332,10 +332,7 @@ <createData entity="CustomerAccountSharingDefault" stepKey="setConfigCustomerAccountDefault"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <!--Do reindex and flush cache--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml index d1f7adb8a902c..9d805b2cf7930 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityDateTest.xml @@ -14,8 +14,8 @@ <title value="Admin should be able to create a Date product attribute"/> <description value="Admin should be able to create a Date product attribute"/> <severity value="BLOCKER"/> - <testCaseId value="MC-10895"/> - <group value="Catalog"/> + <testCaseId value="MC-26021"/> + <group value="catalog"/> <group value="mtf_migrated"/> </annotations> @@ -34,7 +34,7 @@ <!--Generate date for use as default value, needs to be MM/d/YYYY and mm/d/yy--> <generateDate date="now" format="m/j/Y" stepKey="generateDefaultDate"/> - <generateDate date="now" format="m/j/y" stepKey="generateDateCompressedFormat"/> + <generateDate date="now" format="n/j/y" stepKey="generateDateCompressedFormat"/> <!--Navigate to Stores > Attributes > Product.--> <actionGroup ref="AdminOpenProductAttributePageActionGroup" stepKey="goToProductAttributes"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml index ff68bba78cae8..aed2976df8f73 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/EndToEndB2CGuestUserTest/EndToEndB2CGuestUserTest.xml @@ -56,10 +56,7 @@ <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> </after> - <!--Re-index--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Step 1: User browses catalog --> <comment userInput="Start of browsing catalog" stepKey="startOfBrowsingCatalog"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml index 7fd752d7df98d..654dc727b24ca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/ProductAvailableAfterEnablingSubCategoriesTest.xml @@ -50,7 +50,7 @@ <!--Run re-index task--> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> + <argument name="indices" value="catalog_product_price"/> </actionGroup> <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="goToHomepage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml index cde7b14614f8e..3d3867d1efcf1 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontProductsDisplayUsingElasticSearchTest.xml @@ -114,9 +114,7 @@ </createData> <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="performReindex"> - <argument name="indices" value="catalogsearch_fulltext"/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="performReindex"/> <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanFullPageCache"> <argument name="tags" value="full_page"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml index e1b5aca6382e9..64ad348257853 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreLevelTest.xml @@ -74,9 +74,7 @@ </actionGroup> <!-- Logout Admin --> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletion"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml index 0117493906de1..4d04a25c8d12f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StoreFrontRecentlyViewedAtStoreViewLevelTest.xml @@ -66,9 +66,7 @@ <!-- Logout Admin --> <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterDeletion"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml index a73bd5a533ad0..ca561e4af70de 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontCheckDefaultNumberProductsToDisplayTest.xml @@ -187,10 +187,7 @@ <seeInField selector="{{AdminCatalogStorefrontConfigSection.productsPerPageAllowedValues}}" userInput="12,24,36" stepKey="seeDefaultValueAllowedNumberProductsPerPage"/> <seeInField selector="{{AdminCatalogStorefrontConfigSection.productsPerPageDefaultValue}}" userInput="12" stepKey="seeDefaultValueProductPerPage"/> - <!-- Perform reindex and flush cache --> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> <argument name="tags" value=""/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml index 2156178ea88d0..9819357704d44 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontProductNameWithDoubleQuoteTest/StorefrontProductNameWithHTMLEntitiesTest.xml @@ -33,9 +33,7 @@ </after> <!--Run re-index task--> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!--Check product in category listing--> <amOnPage url="{{StorefrontCategoryPage.url($$createCategoryOne.name$$)}}" stepKey="navigateToCategoryPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml index ce04b377300f8..cf1bb065349b6 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/VerifyCategoryProductAndProductCategoryPartialReindexTest.xml @@ -65,9 +65,7 @@ <after> <!-- Change "Category Products" and "Product Categories" indexers to "Update on Save" mode --> <magentoCLI command="indexer:set-mode" arguments="realtime" stepKey="setRealtimeMode"/> - <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> - <argument name="indices" value=""/> - </actionGroup> + <comment userInput="Adding the comment to replace CliIndexerReindexActionGroup action group ('indexer:reindex' commands) for preserving Backward Compatibility" stepKey="reindex"/> <!-- Delete data --> <deleteData createDataKey="productA" stepKey="deleteProductA"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.xml new file mode 100644 index 0000000000000..ed34b460d6158 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontCartDiscountActionGroup.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="AssertStorefrontCartDiscountActionGroup"> + <annotations> + <description>Assert that the provided Discount is present in the Storefront Shopping Cart.</description> + </annotations> + <arguments> + <argument name="discount" type="string" defaultValue="0"/> + </arguments> + <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscount"/> + <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-${{discount}}" stepKey="assertDiscount"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml index 96a236336993f..a30f118bd6207 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleDynamicProductFromShoppingCartTest.xml @@ -56,7 +56,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createBundleDynamicProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml index b64b59ef6109c..d1f452896c84f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/DeleteBundleFixedProductFromShoppingCartTest.xml @@ -48,7 +48,7 @@ <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createFixedBundleProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 38e2203b45258..73a2e4757e954 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -159,7 +159,7 @@ <!-- Add Bundle Product to cart --> <amOnPage url="{{StorefrontProductPage.url($$createFixedBundleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToBundleProductPage"/> <waitForPageLoad stepKey="waitForFixedBundleProductPageLoad"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFixedBundleProductFromStorefrontProductPage"> <argument name="productName" value="$$createFixedBundleProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml index f16f577a4088c..3aa93d72571f9 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontCheckoutDisabledBundleProductTest.xml @@ -59,7 +59,7 @@ <amOnPage url="{{StorefrontProductPage.url($$createBundleDynamicProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToProductPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> <!-- Add bundle product to the cart --> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addProductToCart"> <argument name="productName" value="$$createBundleDynamicProduct.name$$"/> </actionGroup> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml index c58e4ab7513af..f81ee2fc19d5b 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontGuestCheckoutWithCouponAndZeroSubtotalTest.xml @@ -47,8 +47,10 @@ <actionGroup ref="CheckoutFillEstimateShippingAndTaxActionGroup" stepKey="fillEstimateShippingAndTaxFields"/> <!-- Assert Discount and proceed to checkout --> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$50.00" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="50.00"/> + </actionGroup> <actionGroup ref="StorefrontClickProceedToCheckoutActionGroup" stepKey="goToCheckout"/> <comment userInput="Adding the comment to replace waitForPageToLoad action for preserving Backward Compatibility" stepKey="waitForPageToLoad"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml index a8b8cf66f545b..43dd3ead0160c 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontUKCustomerCheckoutWithCouponTest.xml @@ -75,8 +75,10 @@ </actionGroup> <!-- Assert Discount and proceed to checkout --> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$15.00" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="15.00"/> + </actionGroup> <actionGroup ref="StorefrontClickProceedToCheckoutActionGroup" stepKey="goToCheckout"/> <comment userInput="Adding the comment to replace waitForPageToLoad1 action for preserving Backward Compatibility" stepKey="waitForPageToLoad1"/> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickAddNewPageOnPagesGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickAddNewPageOnPagesGridActionGroup.xml new file mode 100644 index 0000000000000..4f48400f53efa --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminClickAddNewPageOnPagesGridActionGroup.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="AdminClickAddNewPageOnPagesGridActionGroup"> + <annotations> + <description>Clicks the "Add New Page" button on the Pages Grid</description> + </annotations> + + <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml index 82e725de46249..711e126afc553 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnCMSPageTest.xml @@ -25,7 +25,7 @@ </before> <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnPagePagesGrid"/> <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPage"/> + <actionGroup ref="AdminClickAddNewPageOnPagesGridActionGroup" stepKey="clickAddNewPage"/> <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{_defaultCmsPage.title}}" stepKey="fillFieldTitle"/> <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickExpandContent"/> <fillField selector="{{CmsNewPagePageContentSection.contentHeading}}" userInput="{{_defaultCmsPage.content_heading}}" stepKey="fillFieldContentHeading"/> diff --git a/app/code/Magento/Csp/etc/config.xml b/app/code/Magento/Csp/etc/config.xml index 6e2235479da93..07761995fdbca 100644 --- a/app/code/Magento/Csp/etc/config.xml +++ b/app/code/Magento/Csp/etc/config.xml @@ -92,6 +92,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </images> <frames> <policy_id>frame-src</policy_id> @@ -120,6 +123,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </fonts> </storefront> <admin> @@ -197,6 +203,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </images> <frames> <policy_id>frame-src</policy_id> @@ -225,6 +234,9 @@ <inline>1</inline> <eval>0</eval> <dynamic>0</dynamic> + <schemes> + <data>data</data> + </schemes> </fonts> </admin> </policies> diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php index 26cac677ccd10..6215909a1fbee 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php @@ -6,6 +6,7 @@ namespace Magento\Customer\Ui\Component\Listing\Column; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Ui\Component\Listing\Columns\Column; @@ -28,7 +29,7 @@ class Confirmation extends Column * @param ScopeConfigInterface $scopeConfig @deprecated * @param array $components * @param array $data - * @param AccountConfirmation $accountConfirmation + * @param AccountConfirmation|null $accountConfirmation * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -65,13 +66,7 @@ public function prepareDataSource(array $dataSource) */ private function getFieldLabel(array $item) { - $isConfirmationRequired = $this->accountConfirmation->isConfirmationRequired( - $item['website_id'][0] ?? null, - $item[$item['id_field_name']], - $item['email'] - ); - - if ($isConfirmationRequired) { + if ($this->getIsConfirmationRequired($item)) { if ($item[$this->getData('name')] === null) { return __('Confirmed'); } @@ -79,4 +74,27 @@ private function getFieldLabel(array $item) } return __('Confirmation Not Required'); } + + /** + * Retrieve is confirmation required flag for customer considering requested website may not exist. + * + * @param array $customer + * @return bool + */ + private function getIsConfirmationRequired(array $customer): bool + { + try { + return $this->accountConfirmation->isConfirmationRequired( + $customer['website_id'][0] ?? null, + $customer[$customer['id_field_name']], + $customer['email'] + ); + } catch (NoSuchEntityException $e) { + return $this->accountConfirmation->isConfirmationRequired( + null, + $customer[$customer['id_field_name']], + $customer['email'] + ); + } + } } diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml index 2ced91731e4ba..0d37c353052ec 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/StorefrontAccountDownloadableProductLinkAfterPartialRefundTest.xml @@ -97,8 +97,8 @@ <argument name="rowNumber" value="1"/> </actionGroup> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <actionGroup ref="StorefrontNotAssertDownloadableProductLinkInCustomerAccountActionGroup" stepKey="dontSeeStorefrontMyAccountDownloadableProductsLink"> <argument name="product" value="$$createDownloadableProduct$$"/> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml index ecbff39807f30..c81c6d36786eb 100644 --- a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityNegativeScenarioTest.xml @@ -129,7 +129,7 @@ <argument name="product" value="$createBundleProduct$"/> </actionGroup> <waitForElementVisible selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="waitForCustomizeAndAddToCartButton"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <waitForPageLoad stepKey="waitForBundleProductPageLoad"/> <dontSeeElement selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="dontSeeButtonOnBundleProductPage"/> <!-- Grouped product --> diff --git a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml index 59697bb6f5bdf..865852c10acfd 100644 --- a/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml +++ b/app/code/Magento/InstantPurchase/Test/Mftf/Test/StorefrontInstantPurchaseFunctionalityTest.xml @@ -109,7 +109,7 @@ <!-- Bundle Product --> <amOnPage url="{{StorefrontProductPage.url($createBundleProduct.custom_attributes[url_key]$)}}" stepKey="openBundleProductPage"/> <waitForElementVisible selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="waitForCustomizeAndAddToCartButton"/> - <click selector="{{StorefrontBundleProductActionSection.customizeAndAddToCartButton}}" stepKey="clickCustomizeAndAddToCart"/> + <actionGroup ref="StorefrontSelectCustomizeAndAddToTheCartButtonActionGroup" stepKey="clickCustomizeAndAddToCart"/> <waitForElementVisible selector="{{StorefrontInstantPurchaseSection.instantPurchaseButton}}" stepKey="waitForButtonOnBundleProductPage"/> <!-- Grouped product --> <amOnPage url="{{StorefrontProductPage.url($createGroupedProduct.custom_attributes[url_key]$)}}" stepKey="openGroupedProductPage"/> diff --git a/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php b/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php index 16c02a7505664..00399e30e8b72 100644 --- a/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php +++ b/app/code/Magento/MessageQueue/Model/ResourceModel/Lock.php @@ -5,46 +5,52 @@ */ namespace Magento\MessageQueue\Model\ResourceModel; -use \Magento\Framework\MessageQueue\Lock\ReaderInterface; -use \Magento\Framework\MessageQueue\Lock\WriterInterface; +use DateInterval; +use DateTime; +use Magento\Framework\MessageQueue\Lock\ReaderInterface; +use Magento\Framework\MessageQueue\Lock\WriterInterface; +use Magento\Framework\MessageQueue\LockInterface; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Magento\MessageQueue\Model\LockFactory; /** * Class Lock to handle database lock table db transactions. */ -class Lock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb implements ReaderInterface, WriterInterface +class Lock extends AbstractDb implements ReaderInterface, WriterInterface { /**#@+ * Constants */ - const QUEUE_LOCK_TABLE = 'queue_lock'; + public const QUEUE_LOCK_TABLE = 'queue_lock'; /**#@-*/ /**#@-*/ private $dateTime; /** - * @var \Magento\MessageQueue\Model\LockFactory + * @var LockFactory */ private $lockFactory; /** - * @var integer + * @var int */ private $interval; /** * Initialize dependencies. * - * @param \Magento\Framework\Model\ResourceModel\Db\Context $context + * @param Context $context * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime - * @param \Magento\MessageQueue\Model\LockFactory $lockFactory - * @param null $connectionName - * @param integer $interval + * @param LockFactory $lockFactory + * @param ?string $connectionName + * @param int $interval */ public function __construct( - \Magento\Framework\Model\ResourceModel\Db\Context $context, + Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $dateTime, - \Magento\MessageQueue\Model\LockFactory $lockFactory, + LockFactory $lockFactory, $connectionName = null, $interval = 86400 ) { @@ -55,7 +61,7 @@ public function __construct( } /** - * {@inheritDoc} + * @inheritdoc */ protected function _construct() { @@ -63,9 +69,9 @@ protected function _construct() } /** - * {@inheritDoc} + * @inheritdoc */ - public function read(\Magento\Framework\MessageQueue\LockInterface $lock, $code) + public function read(LockInterface $lock, $code) { $object = $this->lockFactory->create(); $object->load($code, 'message_code'); @@ -75,23 +81,25 @@ public function read(\Magento\Framework\MessageQueue\LockInterface $lock, $code) } /** - * {@inheritDoc} + * @inheritdoc */ - public function saveLock(\Magento\Framework\MessageQueue\LockInterface $lock) + public function saveLock(LockInterface $lock) { $object = $this->lockFactory->create(); $object->setMessageCode($lock->getMessageCode()); $object->setCreatedAt($this->dateTime->gmtTimestamp()); $object->save(); + $lock->setId($object->getId()); + $lock->setCreatedAt($object->getCreatedAt()); } /** - * {@inheritDoc} + * @inheritdoc */ public function releaseOutdatedLocks() { - $date = (new \DateTime())->setTimestamp($this->dateTime->gmtTimestamp()); - $date->add(new \DateInterval('PT' . $this->interval . 'S')); + $date = (new DateTime())->setTimestamp($this->dateTime->gmtTimestamp()); + $date->add(new DateInterval('PT' . $this->interval . 'S')); $this->getConnection()->delete($this->getTable(self::QUEUE_LOCK_TABLE), ['created_at <= ?' => $date]); } } diff --git a/app/code/Magento/PageCache/etc/varnish6.vcl b/app/code/Magento/PageCache/etc/varnish6.vcl index bce89fe263573..cc381baaf313a 100644 --- a/app/code/Magento/PageCache/etc/varnish6.vcl +++ b/app/code/Magento/PageCache/etc/varnish6.vcl @@ -62,13 +62,13 @@ sub vcl_recv { return (pass); } - # Bypass shopping cart and checkout - if (req.url ~ "/checkout") { + # Bypass customer, shopping cart, checkout + if (req.url ~ "/customer" || req.url ~ "/checkout") { return (pass); } # Bypass health check requests - if (req.url ~ "/pub/health_check.php") { + if (req.url ~ "^/(pub/)?(health_check.php)$") { return (pass); } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php index e923b006a0ac6..1f8d0a0bc265d 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Totals/Tax.php @@ -95,7 +95,7 @@ public function getFullTaxInfo() $taxClassAmount = $this->_taxHelper->getCalculatedTaxes($source); if (empty($taxClassAmount)) { - $rates = $this->_taxOrderFactory->create()->getCollection()->loadByOrder($source)->toArray(); + $rates = $this->_taxOrderFactory->create()->getCollection()->loadByOrder($this->getOrder())->toArray(); $taxClassAmount = $this->_taxCalculation->reproduceProcess($rates['items']); } diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index 6bd6e8e4e83e1..4469bb1496f3c 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -1755,10 +1755,9 @@ public function importPostData($data) if (isset($data['comment'])) { $this->getQuote()->addData($data['comment']); - if (empty($data['comment']['customer_note_notify'])) { - $this->getQuote()->setCustomerNoteNotify(false); - } else { - $this->getQuote()->setCustomerNoteNotify(true); + if ($this->getIsValidate()) { + $notify = !empty($data['comment']['customer_note_notify']); + $this->getQuote()->setCustomerNoteNotify($notify); } } diff --git a/app/code/Magento/Sales/Model/Order/Invoice.php b/app/code/Magento/Sales/Model/Order/Invoice.php index 14dd0b14ac1f3..50bbb3083a9ea 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Order/Invoice.php @@ -679,6 +679,11 @@ public function register() public function isLast() { foreach ($this->getAllItems() as $item) { + $orderItem = $item->getOrderItem(); + if ($orderItem->isDummy()) { + continue; + } + if (!$item->isLast()) { return false; } diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.xml new file mode 100644 index 0000000000000..21ca2d51a364e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminClickRefundOfflineOnNewMemoPageActionGroup.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="AdminClickRefundOfflineOnNewMemoPageActionGroup"> + <annotations> + <description>Click the Refund Offline button on the New Memo page</description> + </annotations> + <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccesMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You created the credit memo." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml index 6ed8510db777c..9d1daf0d2ded1 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoBankTransferPaymentTest.xml @@ -85,8 +85,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <see selector="{{AdminIndexManagementSection.successMessage}}" userInput="You created the credit memo." stepKey="assertRefundSuccessCreateMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml index 68301187d3d31..5d2f76b80e3f8 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoPartialRefundTest.xml @@ -78,8 +78,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <waitForElementVisible selector="{{AdminIndexManagementSection.successMessage}}" stepKey="waitForSuccessMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml index 141fa2a9e5d06..32c3a5e0a5846 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateCreditMemoWithPurchaseOrderTest.xml @@ -88,8 +88,8 @@ </actionGroup> <!-- On order's page click 'Refund offline' button --> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline"/> - <waitForPageLoad stepKey="waitForResultPage"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForResultPage"/> <!-- Perform all assertions: assert refund success create message --> <see selector="{{AdminIndexManagementSection.successMessage}}" userInput="You created the credit memo." stepKey="assertRefundSuccessCreateMessage"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml index d5128dc3f8b0c..96007caf0f8ba 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateInvoiceTest.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="AdminCreateInvoiceTest"> + <test name="AdminCreateInvoiceTest" deprecated="Use AdminInvoiceOrderTest instead"> <annotations> <features value="Sales"/> <stories value="Create an Invoice via the Admin"/> - <title value="Admin should be able to create an invoice"/> + <title value="DEPRECATED. Admin should be able to create an invoice"/> <description value="Admin should be able to create an invoice"/> <severity value="MAJOR"/> <testCaseId value="MAGETWO-72096"/> <group value="sales"/> + <skip> + <issueId value="DEPRECATED">Use AdminInvoiceOrderTest instead</issueId> + </skip> </annotations> <before> <createData entity="_defaultCategory" stepKey="createCategory"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml new file mode 100644 index 0000000000000..922037fe4a3cd --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminInvoiceOrderTest.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminInvoiceOrderTest"> + <annotations> + <features value="Sales"/> + <stories value="Create an Invoice via the Admin"/> + <title value="Admin should be able to create an invoice"/> + <description value="Admin should be able to create an invoice"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-72096"/> + <group value="sales"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProductApi"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="GuestCart" stepKey="createGuestCart"/> + <createData entity="SimpleCartItem" stepKey="addCartItem"> + <requiredEntity createDataKey="createGuestCart"/> + <requiredEntity createDataKey="createSimpleProductApi"/> + </createData> + <createData entity="GuestAddressInformation" stepKey="addGuestOrderAddress"> + <requiredEntity createDataKey="createGuestCart"/> + </createData> + <updateData createDataKey="createGuestCart" entity="GuestOrderPaymentMethod" stepKey="sendGuestPaymentInformation"> + <requiredEntity createDataKey="createGuestCart"/> + </updateData> + + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + + </before> + + <after> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="createSimpleProductApi" stepKey="deleteSimpleProductApi"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> + + <actionGroup ref="AdminOpenOrderByEntityIdActionGroup" stepKey="openOrder"> + <argument name="entityId" value="$createGuestCart.return$"/> + </actionGroup> + + <actionGroup ref="AdminCreateInvoiceActionGroup" stepKey="createInvoice"/> + + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceGridByOrderId"> + <argument name="orderId" value="$createGuestCart.return$"/> + </actionGroup> + + <actionGroup ref="AdminSelectFirstGridRowActionGroup" stepKey="openInvoiceFromGrid"/> + + <actionGroup ref="AdminOrderViewCheckStatusActionGroup" stepKey="checkIfOrderStatusIsProcessing"> + <argument name="status" value="Processing"/> + </actionGroup> + + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml index 6ba1c3ac3deec..2a3284e7e8e35 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/EndToEndB2CAdminTest.xml @@ -140,8 +140,8 @@ <argument name="billingAddress" value="US_Address_TX"/> </actionGroup> <!--Submit credit memo--> - <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="clickRefundOffline" after="verifyOrderCreditMemoInformation"/> - <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the credit memo." stepKey="seeCreditMemoSuccess" after="clickRefundOffline"/> + <actionGroup ref="AdminClickRefundOfflineOnNewMemoPageActionGroup" stepKey="clickRefundOffline" after="verifyOrderCreditMemoInformation"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="seeCreditMemoSuccess" after="clickRefundOffline"/> <click selector="{{AdminOrderDetailsOrderViewSection.creditMemos}}" stepKey="clickOrderCreditMemosTab" after="seeCreditMemoSuccess"/> <waitForLoadingMaskToDisappear stepKey="waitForCreditMemoTabLoadingMask" after="clickOrderCreditMemosTab"/> <see selector="{{AdminOrderCreditMemosTabSection.gridRow('1')}}" userInput="{{Simple_US_Customer.firstname}}" stepKey="seeOrderCreditMemoInTabGrid" after="waitForCreditMemoTabLoadingMask"/> diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php index 80563623e0050..b0c053a36de0f 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Totals/TaxTest.php @@ -5,9 +5,6 @@ */ declare(strict_types=1); -/** - * Test class for \Magento\Sales\Block\Adminhtml\Order\Totals\TaxTest - */ namespace Magento\Sales\Test\Unit\Block\Adminhtml\Order\Totals; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -16,46 +13,75 @@ use Magento\Sales\Model\Order\Creditmemo; use Magento\Sales\Model\Order\Invoice; use Magento\Tax\Helper\Data; +use Magento\Tax\Model\ResourceModel\Sales\Order\Tax\Collection; +use Magento\Tax\Model\Sales\Order\Tax as TaxModel; +use Magento\Tax\Model\Sales\Order\TaxFactory; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Test for \Magento\Sales\Block\Adminhtml\Order\Totals\Tax + */ class TaxTest extends TestCase { - /** @var MockObject|Tax */ + /** + * @var array + */ + private $calculatedData = [ + 'tax' => 'tax', + 'shipping_tax' => 'shipping_tax', + ]; + + /** + * @var MockObject|Tax + */ private $taxMock; + /** + * @var Data|MockObject + */ + private $taxHelperMock; + + /** + * @var TaxFactory|MockObject + */ + private $taxOrderFactory; + + /** + * @inheridoc + */ protected function setUp(): void { - $getCalculatedTax = [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ]; - $taxHelperMock = $this->getMockBuilder(Data::class) - ->setMethods(['getCalculatedTaxes']) + $this->taxHelperMock = $this->getMockBuilder(Data::class) + ->onlyMethods(['getCalculatedTaxes']) ->disableOriginalConstructor() ->getMock(); - $taxHelperMock->expects($this->any()) - ->method('getCalculatedTaxes') - ->willReturn($getCalculatedTax); + $this->taxOrderFactory = $this->createMock(TaxFactory::class); + + $arguments = $this->getModelArguments( + ['taxHelper' => $this->taxHelperMock, 'taxOrderFactory' => $this->taxOrderFactory] + ); $this->taxMock = $this->getMockBuilder(Tax::class) - ->setConstructorArgs($this->_getConstructArguments($taxHelperMock)) - ->setMethods(['getOrder', 'getSource']) + ->setConstructorArgs($arguments) + ->onlyMethods(['getOrder', 'getSource']) ->getMock(); } /** * Test method for getFullTaxInfo * - * @param Order $source - * @param array $getCalculatedTax - * @param array $getShippingTax + * @param Order|null $source * @param array $expectedResult + * @return void * * @dataProvider getFullTaxInfoDataProvider */ - public function testGetFullTaxInfo($source, $expectedResult) + public function testGetFullTaxInfo(?Order $source, array $expectedResult): void { + $this->taxHelperMock->expects($this->any()) + ->method('getCalculatedTaxes') + ->willReturn($this->calculatedData); $this->taxMock->expects($this->once()) ->method('getOrder') ->willReturn($source); @@ -69,13 +95,15 @@ public function testGetFullTaxInfo($source, $expectedResult) * * @param Invoice|Creditmemo $source * @param array $expectedResult + * @return void * * @dataProvider getCreditAndInvoiceFullTaxInfoDataProvider */ - public function testGetFullTaxInfoWithCreditAndInvoice( - $source, - $expectedResult - ) { + public function testGetFullTaxInfoWithCreditAndInvoice($source, array $expectedResult): void + { + $this->taxHelperMock->expects($this->any()) + ->method('getCalculatedTaxes') + ->willReturn($this->calculatedData); $this->taxMock->expects($this->once()) ->method('getSource') ->willReturn($source); @@ -84,19 +112,57 @@ public function testGetFullTaxInfoWithCreditAndInvoice( $this->assertSame($expectedResult, $actualResult); } + /** + * Test method for getFullTaxInfo when order doesn't have tax + * + * @return void + */ + public function testGetFullTaxInfoOrderWithoutTax(): void + { + $this->taxHelperMock->expects($this->once()) + ->method('getCalculatedTaxes') + ->willReturn(null); + + $orderMock = $this->createMock(Order::class); + $taxCollection = $this->createMock(Collection::class); + $taxCollection->expects($this->once()) + ->method('loadByOrder') + ->with($orderMock) + ->willReturnSelf(); + $taxCollection->expects($this->once()) + ->method('toArray') + ->willReturn(['items' => []]); + + $taxOrder = $this->createMock(TaxModel::class); + $taxOrder->expects($this->once()) + ->method('getCollection') + ->willReturn($taxCollection); + $this->taxOrderFactory->expects($this->once()) + ->method('create') + ->willReturn($taxOrder); + + $invoiceMock = $this->createMock(Invoice::class); + $this->taxMock->expects($this->once()) + ->method('getSource') + ->willReturn($invoiceMock); + $this->taxMock->expects($this->once()) + ->method('getOrder') + ->willReturn($orderMock); + + $this->assertNull($this->taxMock->getFullTaxInfo()); + } + /** * Provide the tax helper mock as a constructor argument * - * @param $taxHelperMock + * @param array $arguments * @return array */ - protected function _getConstructArguments($taxHelperMock) + private function getModelArguments(array $arguments): array { $objectManagerHelper = new ObjectManager($this); - return $objectManagerHelper->getConstructArguments( - Tax::class, - ['taxHelper' => $taxHelperMock] - ); + + return $objectManagerHelper->getConstructArguments(Tax::class, $arguments); } /** @@ -106,19 +172,15 @@ protected function _getConstructArguments($taxHelperMock) * * @return array */ - public function getFullTaxInfoDataProvider() + public function getFullTaxInfoDataProvider(): array { - $salesModelOrderMock = $this->getMockBuilder(Order::class) - ->disableOriginalConstructor() - ->getMock(); + $salesModelOrderMock = $this->createMock(Order::class); + return [ 'source is not an instance of \Magento\Sales\Model\Order' => [null, []], 'source is an instance of \Magento\Sales\Model\Order and has reasonable data' => [ $salesModelOrderMock, - [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ], + $this->calculatedData, ] ]; } @@ -130,22 +192,14 @@ public function getFullTaxInfoDataProvider() * * @return array */ - public function getCreditAndInvoiceFullTaxInfoDataProvider() + public function getCreditAndInvoiceFullTaxInfoDataProvider(): array { - $invoiceMock = $this->getMockBuilder(Invoice::class) - ->disableOriginalConstructor() - ->getMock(); - $creditMemoMock = $this->getMockBuilder(Creditmemo::class) - ->disableOriginalConstructor() - ->getMock(); + $invoiceMock = $this->createMock(Invoice::class); + $creditMemoMock = $this->createMock(Creditmemo::class); - $expected = [ - 'tax' => 'tax', - 'shipping_tax' => 'shipping_tax', - ]; return [ - 'invoice' => [$invoiceMock, $expected], - 'creditMemo' => [$creditMemoMock, $expected] + 'invoice' => [$invoiceMock, $this->calculatedData], + 'creditMemo' => [$creditMemoMock, $this->calculatedData] ]; } } diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml index 88853b2c40d9a..96da616818ae1 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleAndVerifyRuleConditionAndFreeShippingIsAppliedTest.xml @@ -107,6 +107,8 @@ <argument name="total" value="$280.00"/> </actionGroup> <see selector="{{CheckoutCartSummarySection.shipping}}" userInput="$0.00" stepKey="seeAssertFreeShippingConditionApplied"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForMatchingItemsConditionIsTrue"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeAssertDiscountAmountAppliedForMatchingItemsConditionIsTrue"> + <argument name="discount" value="280.00"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml index e206633808057..65bb0b4cbfb99 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleEmptyFromDateTest.xml @@ -87,8 +87,10 @@ <argument name="coupon" value="_defaultCoupon"/> </actionGroup> <waitForPageLoad stepKey="waitForProductPageLoad2"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$5.00" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="5.00"/> + </actionGroup> <!--Reset timezone--> <actionGroup ref="AdminOpenGeneralConfigurationPageActionGroup" stepKey="goToGeneralConfigReset"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml index 16af210066997..198ba1cd64f35 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForCouponCodeTest.xml @@ -80,7 +80,9 @@ <argument name="coupon" value="_defaultCoupon"/> </actionGroup> <waitForPageLoad stepKey="waitForProductPageLoad2"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$5.00" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="5.00"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml index b3d81cea7f97f..bc2f115b46873 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForGeneratedCouponTest.xml @@ -84,7 +84,9 @@ <waitForElementVisible selector="{{StorefrontSalesRuleCartCouponSection.couponField}}" stepKey="waitForCouponField" /> <fillField selector="{{StorefrontSalesRuleCartCouponSection.couponField}}" userInput="{$grabCouponCode}" stepKey="fillCouponField"/> <click selector="{{StorefrontSalesRuleCartCouponSection.applyButton}}" stepKey="clickApplyButton"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$0.99" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="0.99"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml index da8c8e4bc1f9d..1fe97b1f45036 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleForMatchingSubtotalAndVerifyRuleConditionIsAppliedTest.xml @@ -116,6 +116,8 @@ <argument name="shippingMethod" value="Flat Rate - Fixed"/> <argument name="total" value="$285.00"/> </actionGroup> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForSubtotalConditionIsTrue"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeAssertDiscountAmountAppliedForSubtotalConditionIsTrue"> + <argument name="discount" value="280.00"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml index f6e736c73db74..c80f43385d166 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingCategoryAndVerifyRuleConditionIsAppliedTest.xml @@ -118,6 +118,8 @@ <argument name="shippingMethod" value="Flat Rate - Fixed"/> <argument name="total" value="$66.50"/> </actionGroup> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$61.50" stepKey="seeAssertDiscountAmountAppliedForMatchingCategory"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeAssertDiscountAmountAppliedForMatchingCategory"> + <argument name="discount" value="61.50"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml index 5f110f7074f6f..cd72ec8529816 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/AdminCreateCartPriceRuleWithMatchingTotalWeightAndVerifyRuleConditionIsAppliedTest.xml @@ -106,6 +106,8 @@ <argument name="shippingMethod" value="Flat Rate - Fixed"/> <argument name="total" value="$285.00"/> </actionGroup> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$280.00" stepKey="seeAssertDiscountAmountAppliedForWeightConditionIsTrue"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeAssertDiscountAmountAppliedForWeightConditionIsTrue"> + <argument name="discount" value="280.00"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml index ea96fa41e5cad..3b54df544210f 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleCountryTest.xml @@ -77,8 +77,10 @@ <!-- See discount if we use valid country --> <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="Brazil" stepKey="fillCountry"/> <waitForPageLoad stepKey="waitForCountry1"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="9.99"/> + </actionGroup> <!-- Do not see discount with other country --> <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="fillCountry2"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml index 62c494b988bbd..d0cba156f635e 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRulePostcodeTest.xml @@ -81,8 +81,10 @@ <!-- See discount if we use valid postcode --> <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="78613" stepKey="fillPostcode"/> <waitForPageLoad stepKey="waitForPostcode1"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="9.99"/> + </actionGroup> <!-- Do not see discount with other postcode --> <fillField selector="{{CheckoutCartSummarySection.postcode}}" userInput="90210" stepKey="fillPostcode2"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml index 70ed09df7a2cc..1a449017e0386 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleQuantityTest.xml @@ -83,7 +83,9 @@ <!-- Now we should see the discount because we have more than 1 item --> <actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="goToCartPage2"/> <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$246.00" stepKey="seeSubtotal2"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$1.00" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="1.00"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml index da9ca9055d31b..68f6fc93eab94 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleStateTest.xml @@ -77,8 +77,10 @@ <!-- See discount if we use valid postcode --> <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Indiana" stepKey="fillState"/> <waitForPageLoad stepKey="waitForPostcode1"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$9.99" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="9.99"/> + </actionGroup> <!-- Do not see discount with other postcode --> <selectOption selector="{{CheckoutCartSummarySection.stateProvince}}" userInput="Texas" stepKey="fillState2"/> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml index ce0d814e50308..0ffe1516d0232 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartPriceRuleSubtotalTest.xml @@ -81,7 +81,9 @@ <!-- Now we should see the discount because we exceeded $200 --> <actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="goToCartPage2"/> <see selector="{{CheckoutCartSummarySection.subtotal}}" userInput="$246.00" stepKey="seeSubtotal2"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForDiscountElement"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$0.01" stepKey="seeDiscountTotal"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForDiscountElement"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountTotal"> + <argument name="discount" value="0.01"/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml index 1178ca2cfb328..8df45937bb542 100644 --- a/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml +++ b/app/code/Magento/SalesRule/Test/Mftf/Test/StorefrontCartTotalValueWithFullDiscountUsingCartRuleTest.xml @@ -117,8 +117,10 @@ <actionGroup ref="StorefrontCartPageOpenActionGroup" stepKey="amOnPageShoppingCart"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.orderTotal}}" stepKey="waitForOrderTotalVisible"/> <selectOption selector="{{CheckoutCartSummarySection.country}}" userInput="United States" stepKey="selectCountry"/> - <waitForElementVisible selector="{{CheckoutCartSummarySection.discountAmount}}" stepKey="waitForOrderTotalUpdate"/> - <see selector="{{CheckoutCartSummarySection.discountAmount}}" userInput="-$29.00" stepKey="seeDiscountAmount"/> + <comment userInput="Adding the comment to replace action for preserving Backward Compatibility" stepKey="waitForOrderTotalUpdate"/> + <actionGroup ref="AssertStorefrontCartDiscountActionGroup" stepKey="seeDiscountAmount"> + <argument name="discount" value="29.00"/> + </actionGroup> <see selector="{{CheckoutCartSummarySection.subTotal}}" userInput="$29.00" stepKey="seeSubTotal"/> <see selector="{{CheckoutCartSummarySection.orderTotal}}" userInput="0.00" stepKey="seeOrderTotal"/> </test> diff --git a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js index 0ac35df78e001..45dfaa40f87df 100644 --- a/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js +++ b/app/code/Magento/Ui/view/base/web/js/dynamic-rows/dynamic-rows.js @@ -620,15 +620,12 @@ define([ * @param {Array} data */ parsePagesData: function (data) { - var pages; - this.relatedData = this.deleteProperty ? _.filter(data, function (elem) { return elem && elem[this.deleteProperty] !== this.deleteValue; }, this) : data; - pages = Math.ceil(this.relatedData.length / this.pageSize) || 1; - this.pages(pages); + this._updatePagesQuantity(); }, /** @@ -885,6 +882,18 @@ define([ this._sort(); }, + /** + * Update number of pages. + * + * @private + * @return void + */ + _updatePagesQuantity: function () { + var pages = Math.ceil(this.relatedData.length / this.pageSize) || 1; + + this.pages(pages); + }, + /** * Reduce the number of pages * @@ -960,6 +969,7 @@ define([ reload: function () { this.clear(); this.initChildren(false, true); + this._updatePagesQuantity(); /* After change page size need to check existing current page */ this._reducePages(); diff --git a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml index 04218c76a4b7b..ef9093667d479 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml @@ -34,7 +34,7 @@ <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnCmsList"/> <waitForPageLoad stepKey="waitForCmsList"/> - <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPageButton"/> + <actionGroup ref="AdminClickAddNewPageOnPagesGridActionGroup" stepKey="clickAddNewPageButton"/> <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{_newDefaultCmsPage.title}}" stepKey="fillPageTitle"/> <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="expandContentSection"/> <waitForPageLoad stepKey="waitForContentSection"/> diff --git a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml index 593b0df3f3a02..e9fcdf436d90b 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml @@ -35,7 +35,7 @@ <amOnPage url="{{CmsPagesPage.url}}" stepKey="amOnCmsList"/> <waitForPageLoad stepKey="waitForCmsList"/> <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clickClearFilters"/> - <click selector="{{CmsPagesPageActionsSection.addNewPageButton}}" stepKey="clickAddNewPageButton"/> + <actionGroup ref="AdminClickAddNewPageOnPagesGridActionGroup" stepKey="clickAddNewPageButton"/> <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{_newDefaultCmsPage.title}}" stepKey="fillPageTitle"/> <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="expandContentSection"/> <waitForPageLoad stepKey="waitForContentSection"/> diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php index 5623edca62b9a..2e8eedf96b0f8 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CategoryRepositoryTest.php @@ -184,22 +184,51 @@ public function testDeleteNoSuchEntityException() /** * @dataProvider deleteSystemOrRootDataProvider + * + * @param int $categoryId + * @param string $exceptionMsg + * @return void */ - public function testDeleteSystemOrRoot() + public function testDeleteSystemOrRoot(int $categoryId, string $exceptionMsg): void { $this->expectException(\Exception::class); + $this->expectExceptionMessage($exceptionMsg); - $this->deleteCategory($this->modelId); + $this->deleteCategory($categoryId); } - public function deleteSystemOrRootDataProvider() + /** + * @return array + */ + public function deleteSystemOrRootDataProvider(): array { return [ - [Category::TREE_ROOT_ID], - [2] //Default root category + 'system_category' => [ + 'category_id' => Category::TREE_ROOT_ID, + 'exception_message' => $this->buildExceptionMessage(Category::TREE_ROOT_ID), + ], + 'root_category' => [ + 'category_id' => 2, + 'exception_message' => $this->buildExceptionMessage(2), + ], ]; } + /** + * Build response error message + * + * @param int $categoryId + * @return string + */ + private function buildExceptionMessage(int $categoryId): string + { + $translatedMsg = (string)__('Cannot delete category with id %1'); + + return TESTS_WEB_API_ADAPTER === self::ADAPTER_REST + ? sprintf('{"message":"%s","parameters":["%u"]}', $translatedMsg, $categoryId) + : $translatedMsg; + } + /** * @magentoApiDataFixture Magento/Catalog/_files/category.php */ diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php new file mode 100644 index 0000000000000..0bbed6387ae57 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductWebsiteLinkRepositoryTest.php @@ -0,0 +1,109 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Api; + +use Magento\Catalog\Model\ProductWebsiteLink; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; + +/** + * Tests to check products to websites assigning. + * + * @see \Magento\Catalog\Model\ProductWebsiteLinkRepository + * + * @magentoAppIsolation enabled + */ +class ProductWebsiteLinkRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductWebsiteLinkRepositoryV1'; + const SERVICE_VERSION = 'V1'; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testSaveWebsiteLinkWithUnexistingWebsiteId(): void + { + $pattern = '/(Could\\snot\\sassign\\sproduct)+([\\s\\S]*)(to\\swebsites)+([\\s\\S]*)/'; + $unexistingWebsiteId = 8932568989; + $serviceInfo = $this->fillServiceInfo('/V1/products/:sku/websites', Request::HTTP_METHOD_POST, 'Save'); + $requestData = [ + 'productWebsiteLink' => [ + ProductWebsiteLink::KEY_SKU => 'simple2', + ProductWebsiteLink::WEBSITE_ID => $unexistingWebsiteId, + ], + ]; + $this->expectException(\Exception::class); + $this->expectExceptionMessageMatches($pattern); + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_with_two_websites.php + * + * @return void + */ + public function testDeleteWebsiteLink(): void + { + $productSku = 'unique-simple-azaza'; + $websiteId = (int)$this->websiteRepository->get('second_website')->getId(); + $resourcePath = sprintf('/V1/products/%s/websites/%u', $productSku, $websiteId); + $serviceInfo = $this->fillServiceInfo($resourcePath, Request::HTTP_METHOD_DELETE, 'DeleteById'); + $this->_webApiCall( + $serviceInfo, + [ProductWebsiteLink::KEY_SKU => $productSku, ProductWebsiteLink::WEBSITE_ID => $websiteId] + ); + $product = $this->productRepository->get($productSku, false, null, true); + $this->assertNotContains($websiteId, $product->getWebsiteIds()); + } + + /** + * Fill service information + * + * @param string $resourcePath + * @param string $httpMethod + * @param string $operation + * @return array + */ + private function fillServiceInfo(string $resourcePath, string $httpMethod, string $operation): array + { + return [ + 'rest' => ['resourcePath' => $resourcePath, 'httpMethod' => $httpMethod], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . $operation, + ], + ]; + } +} diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php index fb6fd4c5c2802..3d2f722ccb60e 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/Model/Processor.php @@ -5,13 +5,16 @@ */ namespace Magento\TestModuleMysqlMq\Model; +use LogicException; +use Magento\Framework\MessageQueue\ConnectionLostException; + /** * Test message processor is used by \Magento\MysqlMq\Model\PublisherConsumerTest */ class Processor { /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processMessage($message) { @@ -23,7 +26,7 @@ public function processMessage($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processObjectCreated($message) { @@ -35,7 +38,7 @@ public function processObjectCreated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processCustomObjectCreated($message) { @@ -47,7 +50,7 @@ public function processCustomObjectCreated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processObjectUpdated($message) { @@ -59,13 +62,23 @@ public function processObjectUpdated($message) } /** - * @param \Magento\TestModuleMysqlMq\Model\DataObject $message + * @param DataObject $message */ public function processMessageWithException($message) { file_put_contents($message->getOutputPath(), "Exception processing {$message->getEntityId()}"); - throw new \LogicException( + throw new LogicException( "Exception during message processing happened. Entity: {{$message->getEntityId()}}" ); } + + /** + * @throws ConnectionLostException + */ + public function processMessageWithConnectionException() + { + throw new ConnectionLostException( + "Connection exception during message processing happened." + ); + } } diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml index 4d6269dbb7920..1a5a5feb11324 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/communication.xml @@ -7,6 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd"> <topic name="demo.exception" request="Magento\TestModuleMysqlMq\Model\DataObject"/> + <topic name="demo.connection.exception" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="test.schema.defined.by.method" schema="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation" is_synchronous="false"/> <topic name="demo.object.created" request="Magento\TestModuleMysqlMq\Model\DataObject"/> <topic name="demo.object.updated" request="Magento\TestModuleMysqlMq\Model\DataObject"/> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml index 362237c0c5e62..c879b271c6651 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue.xml @@ -9,6 +9,9 @@ <broker topic="demo.exception" type="db" exchange="magento"> <queue consumer="demoConsumerWithException" name="queue-exception" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithException"/> </broker> + <broker topic="demo.connection.exception" type="db" exchange="magento"> + <queue consumer="demoConsumerWithConnectionException" name="queue-connection-exception" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithConnectionException"/> + </broker> <broker topic="test.schema.defined.by.method" type="db" exchange="magento"> <queue consumer="delayedOperationConsumer" name="demo-queue-6" handler="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation"/> </broker> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml index bb495a123a05d..6a3916a23b43b 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_consumer.xml @@ -10,5 +10,6 @@ <consumer name="demoConsumerQueueTwo" queue="queue-updated" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processObjectUpdated"/> <consumer name="demoConsumerQueueThree" queue="queue-custom-created" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processCustomObjectCreated"/> <consumer name="demoConsumerWithException" queue="queue-exception" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithException"/> + <consumer name="demoConsumerWithConnectionException" queue="queue-connection-exception" connection="db" handler="Magento\TestModuleMysqlMq\Model\Processor::processMessageWithConnectionException"/> <consumer name="delayedOperationConsumer" queue="demo-queue-6" connection="db" handler="Magento\TestModuleMysqlMq\Model\DataObjectRepository::delayedOperation"/> </config> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml index a665e10ef5f14..639503a936cb5 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_publisher.xml @@ -9,6 +9,9 @@ <publisher topic="demo.exception"> <connection name="db" exchange="magento"/> </publisher> + <publisher topic="demo.connection.exception"> + <connection name="db" exchange="magento"/> + </publisher> <publisher topic="test.schema.defined.by.method"> <connection name="db" exchange="magento"/> </publisher> diff --git a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml index 2df5485ee3447..3612438c37f4a 100644 --- a/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml +++ b/dev/tests/integration/_files/Magento/TestModuleMysqlMq/etc/queue_topology.xml @@ -9,6 +9,7 @@ <exchange name="magento" type="topic" connection="db"> <binding id="demo.exception.consumer" topic="demo.exception" destination="queue-exception" destinationType="queue"/> + <binding id="demo.connection.exception.consumer" topic="demo.connection.exception" destination="queue-connection-exception" destinationType="queue"/> <binding id="test.schema.defined.by.method" topic="test.schema.defined.by.method" destination="demo-queue-6" destinationType="queue"/> <binding id="demo.object.created" topic="demo.object.created" destination="queue-created" destinationType="queue"/> <binding id="demo.object.updated" topic="demo.object.updated" destination="queue-updated" destinationType="queue"/> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php new file mode 100644 index 0000000000000..b9ccfd6d52458 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Check stock alert grid + * + * @see \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts\Stock + * + * @magentoAppArea adminhtml + */ +class StockTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Stock */ + private $block; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Stock::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @dataProvider alertsDataProvider + * + * @magentoDbIsolation disabled + * @magentoDataFixture Magento/ProductAlert/_files/product_alert.php + * @magentoDataFixture Magento/ProductAlert/_files/stock_alert_on_second_website.php + * + * @param string $sku + * @param string $expectedEmail + * @param string|null $storeCode + * @return void + */ + public function testGridCollectionWithStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void + { + $productId = (int)$this->productRepository->get($sku)->getId(); + $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : null; + $this->block->getRequest()->setParams(['id' => $productId, 'store' => $storeId]); + $collection = $this->block->getPreparedCollection(); + $this->assertCount(1, $collection); + $this->assertEquals($expectedEmail, $collection->getFirstItem()->getEmail()); + } + + /** + * @return array + */ + public function alertsDataProvider(): array + { + return [ + 'without_store_id_filter' => [ + 'product_sku' => 'simple', + 'expected_customer_emails' => 'customer@example.com', + ], + 'with_store_id_filter' => [ + 'product_sku' => 'simple_on_second_website', + 'expected_customer_emails' => 'customer_second_ws_with_addr@example.com', + 'store_code' => 'fixture_third_store', + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php index 91a54d8fc13fa..d21fdf190c0b8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/View/Options/Type/DateTest.php @@ -20,6 +20,7 @@ /** * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DateTest extends TestCase { @@ -96,9 +97,10 @@ protected function tearDown(): void } /** - * @magentoAppArea frontend * @param array $data * @param array $expected + * @magentoAppArea frontend + * @magentoConfigFixture current_store catalog/custom_options/year_range 2020,2030 * @dataProvider toHtmlWithDropDownDataProvider */ public function testToHtmlWithDropDown(array $data, array $expected): void @@ -108,11 +110,12 @@ public function testToHtmlWithDropDown(array $data, array $expected): void } /** - * @magentoAppArea frontend - * @magentoConfigFixture current_store catalog/custom_options/use_calendar 1 * @param array $data * @param array $expected * @param string|null $locale + * @magentoAppArea frontend + * @magentoConfigFixture current_store catalog/custom_options/use_calendar 1 + * @magentoConfigFixture current_store catalog/custom_options/year_range 2020,2030 * @dataProvider toHtmlWithCalendarDataProvider */ public function testToHtmlWithCalendar(array $data, array $expected, ?string $locale = null): void diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php new file mode 100644 index 0000000000000..24d5b668ac09c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/StockTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Attribute\Backend; + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Model\Product; +use Magento\Eav\Model\Config; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Test class for backend stock attribute model. + * + * @see \Magento\Catalog\Model\Product\Attribute\Backend\Stock + * + * @magentoAppArea adminhtml + */ +class StockTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductInterfaceFactory */ + private $productFactory; + + /** @var Stock */ + private $model; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productFactory = $this->objectManager->get(ProductInterfaceFactory::class); + $this->model = $this->objectManager->get(Stock::class); + $this->model->setAttribute( + $this->objectManager->get(Config::class)->getAttribute(Product::ENTITY, 'quantity_and_stock_status') + ); + } + + /** + * @return void + */ + public function testValidate(): void + { + $this->expectException(LocalizedException::class); + $this->expectErrorMessage((string)__('Please enter a valid number in this field.')); + $product = $this->productFactory->create(); + $product->setQuantityAndStockStatus(['qty' => 'string']); + $this->model->validate($product); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php new file mode 100644 index 0000000000000..7430ebf72f8fb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/RepositoryTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Attribute; + +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory; +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Setup\CategorySetup; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; +use Magento\Framework\Exception\InputException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks product attribute save behaviour. + * + * @see \Magento\Catalog\Model\Product\Attribute\Repository + * + * @magentoDbIsolation enabled + */ +class RepositoryTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductAttributeRepositoryInterface */ + private $repository; + + /** @var ProductAttributeInterfaceFactory */ + private $attributeFactory; + + /** @var ProductAttributeInterface */ + private $createdAttribute; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->repository = $this->objectManager->get(ProductAttributeRepositoryInterface::class); + $this->attributeFactory = $this->objectManager->get(ProductAttributeInterfaceFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + if ($this->createdAttribute instanceof ProductAttributeInterface) { + $this->repository->delete($this->createdAttribute); + } + + parent::tearDown(); + } + + /** + * @return void + */ + public function testSaveWithoutAttributeCode(): void + { + $this->createdAttribute = $this->saveAttributeWithData( + $this->hydrateData(['frontend_label' => 'Boolean Attribute']) + ); + $this->assertEquals('boolean_attribute', $this->createdAttribute->getAttributeCode()); + } + + /** + * @return void + */ + public function testSaveWithoutAttributeAndInvalidLabelCode(): void + { + $this->createdAttribute = $this->saveAttributeWithData($this->hydrateData(['frontend_label' => '/$&!/'])); + $this->assertStringStartsWith('attr_', $this->createdAttribute->getAttributeCode()); + } + + /** + * @dataProvider errorProvider + * + * @param string $fieldName + * @param string $fieldValue + * @return void + */ + public function testSaveWithInvalidCode(string $fieldName, string $fieldValue): void + { + $this->expectExceptionObject(InputException::invalidFieldValue($fieldName, $fieldValue)); + $this->createdAttribute = $this->saveAttributeWithData($this->hydrateData([$fieldName => $fieldValue])); + } + + /** + * @return array + */ + public function errorProvider(): array + { + return [ + 'with_invalid_attribute_code' => [ + 'field_name' => 'attribute_code', + 'field_value' => '****', + ], + 'with_invalid_frontend_input' => [ + 'field_name' => 'frontend_input', + 'field_value' => 'invalid_input', + ], + ]; + } + + /** + * Save product attribute with data + * + * @param array $data + * @return ProductAttributeInterface + */ + private function saveAttributeWithData(array $data): ProductAttributeInterface + { + $attribute = $this->attributeFactory->create(); + $attribute->addData($data); + + return $this->repository->save($attribute); + } + + /** + * Hydrate data + * + * @param array $data + * @return array + */ + private function hydrateData(array $data): array + { + $defaultData = [ + 'entity_type_id' => CategorySetup::CATALOG_PRODUCT_ENTITY_TYPE_ID, + 'is_global' => ScopedAttributeInterface::SCOPE_GLOBAL, + 'frontend_input' => 'boolean', + 'frontend_label' => 'default label', + ]; + + return array_merge($defaultData, $data); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php new file mode 100644 index 0000000000000..9ae327036971b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductWebsiteLinkRepositoryTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model; + +use Magento\Catalog\Api\Data\ProductWebsiteLinkInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Api\ProductWebsiteLinkRepositoryInterface; +use Magento\Framework\Exception\InputException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests to check products to websites assigning. + * + * @see \Magento\Catalog\Model\ProductWebsiteLinkRepository + * + * @magentoAppIsolation enabled + */ +class ProductWebsiteLinkRepositoryTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ProductWebsiteLinkRepositoryInterface */ + private $productWebsiteLinkRepository; + + /** @var ProductWebsiteLinkInterfaceFactory */ + private $productWebsiteLinkFactory; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->productWebsiteLinkRepository = $this->objectManager->get(ProductWebsiteLinkRepositoryInterface::class); + $this->productWebsiteLinkFactory = $this->objectManager->get(ProductWebsiteLinkInterfaceFactory::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testSaveWithoutWebsiteId(): void + { + $productWebsiteLink = $this->productWebsiteLinkFactory->create(); + $productWebsiteLink->setSku('unique-simple-azaza'); + $this->expectException(InputException::class); + $this->expectErrorMessage((string)__('There are not websites for assign to product')); + $this->productWebsiteLinkRepository->save($productWebsiteLink); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_with_two_websites.php + * + * @return void + */ + public function testDelete(): void + { + $this->markTestSkipped('Blocked by MC-40250'); + $productWebsiteLink = $this->productWebsiteLinkFactory->create(); + $productWebsiteLink->setSku('unique-simple-azaza'); + $productWebsiteLink->setWebsiteId(1); + $this->productWebsiteLinkRepository->delete($productWebsiteLink); + $product = $this->productRepository->get('unique-simple-azaza', false, null, true); + $this->assertEquals([$this->websiteRepository->get('second_website')->getId()], $product->getWebsiteIds()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php new file mode 100644 index 0000000000000..9979e8cd6ea68 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/SuffixTest.php @@ -0,0 +1,287 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\System\Config\Backend\Catalog\Url\Rewrite; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; +use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; +use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\Framework\App\Cache\Type\Block; +use Magento\Framework\App\Cache\Type\Collection; +use Magento\Framework\App\Cache\TypeListInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\Storage\DbStorage; +use PHPUnit\Framework\TestCase; + +/** + * Class checks url suffix config save behaviour + * + * @see \Magento\Catalog\Model\System\Config\Backend\Catalog\Url\Rewrite\Suffix + * + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class SuffixTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Suffix */ + private $model; + + /** @var DbStorage */ + private $urlFinder; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var TypeListInterface */ + private $typeList; + + /** @var ScopeConfigInterface */ + private $scopeConfig; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var int */ + private $defaultStoreId; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(Suffix::class); + $this->urlFinder = $this->objectManager->get(DbStorage::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->typeList = $this->objectManager->get(TypeListInterface::class); + $this->scopeConfig = $this->objectManager->get(ScopeConfigInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->defaultStoreId = (int)$this->storeManager->getStore('default')->getId(); + } + + /** + * @return void + */ + public function testSaveWithError(): void + { + $this->expectException(LocalizedException::class); + $this->expectErrorMessage((string)__('Anchor symbol (#) is not supported in url rewrite suffix.')); + $this->model->setValue('.html#'); + $this->model->beforeSave(); + } + + /** + * @dataProvider wrongValuesProvider + * + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @param array $data + * @return void + */ + public function testSaveWithWrongData(array $data): void + { + $productId = (int)$this->productRepository->get('simple2')->getId(); + $this->model->addData($data); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + } + + /** + * @return array + */ + public function wrongValuesProvider(): array + { + return [ + 'with_wrong_path' => [ + ['path' => 'wrong_path', 'value' => 'some_test_value'], + ], + 'with_null_value' => [ + ['path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, 'value' => null], + ], + ]; + } + + /** + * @magentoDbIsolation disabled + * + * @magentoDataFixture Magento/Catalog/_files/product_multistore_different_short_description.php + * + * @return void + */ + public function testSaveInStoreScope(): void + { + $productId = $this->productRepository->get('simple-different-short-description')->getId(); + $newSuffix = 'some_test_value_for_store'; + $storeId = $this->storeManager->getStore('fixturestore')->getId(); + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + 'scope' => ScopeInterface::SCOPE_STORES, + 'scope_id' => $storeId, + ]); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + $this->assertRewrite( + $newSuffix, + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $storeId, + ] + ); + } + + /** + * @magentoDbIsolation disabled + * + * @magentoDataFixture Magento/Catalog/_files/product_two_websites.php + * + * @return void + */ + public function testSaveInWebsiteScope(): void + { + $productId = (int)$this->productRepository->get('simple-on-two-websites')->getId(); + $newSuffix = 'some_test_value_for_website'; + $website = $this->storeManager->getWebsite('test'); + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + 'scope' => ScopeInterface::SCOPE_WEBSITES, + 'scope_id' => $website->getId(), + ]); + $this->model->afterSave(); + $this->assertRewrite( + $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX), + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + $this->assertRewrite( + $newSuffix, + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $website->getStoreIds(), + ] + ); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @magentoConfigFixture default_store catalog/seo/product_url_suffix .html_default + * + * @return void + */ + public function testSaveDefaultScopeWithOverrideStoreScope(): void + { + $productId = (int)$this->productRepository->get('simple2')->getId(); + $newSuffix = 'some_test_value'; + $this->model->addData([ + 'path' => ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX, + 'value' => $newSuffix, + ]); + $this->model->afterSave(); + $this->assertRewrite( + '.html_default', + [ + 'entity_type' => ProductUrlRewriteGenerator::ENTITY_TYPE, + 'entity_id' => $productId, + 'store_id' => $this->defaultStoreId, + ] + ); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category.php + * + * @return void + */ + public function testSaveCategorySuffix(): void + { + $this->model->addData(['path' => CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX, 'value' => null]); + $this->model->afterSave(); + $this->assertRewrite('.html', ['entity_type' => CategoryUrlRewriteGenerator::ENTITY_TYPE]); + $this->checkIsCacheInvalidated(); + } + + /** + * @return void + */ + public function testDeleteCategorySuffix(): void + { + $this->model->addData( + ['path' => CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX, 'value' => 'test_value'] + ); + $this->model->afterDeleteCommit(); + $this->checkIsCacheInvalidated(); + } + + /** + * Check that provided cache types are invalidated + * + * @param array $cacheTypes + * @return void + */ + private function checkIsCacheInvalidated( + array $cacheTypes = [Block::TYPE_IDENTIFIER, Collection::TYPE_IDENTIFIER] + ): void { + $types = $this->typeList->getTypes(); + + foreach ($cacheTypes as $type) { + $this->assertNotNull($types[$type]); + $this->assertEquals(0, $types[$type]->getStatus()); + } + } + + /** + * Assert url rewrite rewrite + * + * @param string $expectedSuffix + * @param array $data + * @return void + */ + private function assertRewrite(string $expectedSuffix, array $data): void + { + $rewrite = $this->urlFinder->findOneByData($data); + $this->assertNotNull($rewrite); + $this->assertTrue( + substr($rewrite->getRequestPath(), -strlen($expectedSuffix)) === $expectedSuffix, + 'The url rewrite suffix does not match expected value' + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php new file mode 100644 index 0000000000000..96ddc66c875b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; + +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\Xpath; +use PHPUnit\Framework\TestCase; + +/** + * Alerts modifier test + * + * @see \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Alerts + * + * @magentoAppArea adminhtml + */ +class AlertsTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Alerts */ + private $stockAlertsModifier; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->stockAlertsModifier = $this->objectManager->get(Alerts::class); + } + + /** + * @magentoConfigFixture current_store catalog/productalert/allow_stock 1 + * + * @return void + */ + public function testModifyMeta(): void + { + $meta = $this->stockAlertsModifier->modifyMeta([]); + $this->assertArrayHasKey('alerts', $meta); + $content = $meta['alerts']['children'][Alerts::DATA_SCOPE_STOCK]['arguments']['data']['config']['content']; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath("//div[@data-grid-id='alertStock']", $content) + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php new file mode 100644 index 0000000000000..279e45fc868cc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/BackordersTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Model\Config\Backend; + +use Magento\CatalogInventory\Model\Configuration; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; +use Magento\CatalogInventory\Model\Stock; +use Magento\Config\Model\Config\BackendFactory; +use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\Indexer\StateInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks that the backorders config backend model is working correctly + */ +class BackordersTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Backorders */ + private $backorders; + + /** @var BackendFactory */ + private $backendFactory; + + /** @var MutableScopeConfigInterface */ + private $mutableConfig; + + /** @var Processor */ + private $stockIndexerProcessor; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->backendFactory = $this->objectManager->create(BackendFactory::class); + $this->backorders = $this->backendFactory->create(Backorders::class, [ + 'data' => [ + 'path' => Configuration::XML_PATH_BACKORDERS, + ] + ]); + $this->mutableConfig = $this->objectManager->get(MutableScopeConfigInterface::class); + $this->stockIndexerProcessor = $this->objectManager->get(Processor::class); + } + + /** + * @dataProvider afterSaveDataProvider + * @param int $value + * @param int $currentValue + * @param string $expectedIndexerStatus + * @magentoDbIsolation disabled + * @return void + */ + public function testAfterSave(int $value, int $currentValue, string $expectedIndexerStatus): void + { + $this->stockIndexerProcessor->reindexAll(); + $this->mutableConfig->setValue(Configuration::XML_PATH_BACKORDERS, $currentValue); + $this->backorders->setValue((string)$value); + $this->backorders->afterSave(); + + $this->assertEquals($expectedIndexerStatus, $this->stockIndexerProcessor->getIndexer()->getStatus()); + } + + /** + * Data provider for testAfterSave + * + * @return array + */ + public function afterSaveDataProvider(): array + { + return [ + 'set_backorders' => [ + 'value' => Stock::BACKORDERS_YES_NONOTIFY, + 'current_value' => Stock::BACKORDERS_NO, + 'expected_indexer_status' => StateInterface::STATUS_INVALID, + ], + 'unset_backorders' => [ + 'value' => Stock::BACKORDERS_NO, + 'current_value' => Stock::BACKORDERS_YES_NONOTIFY, + 'expected_indexer_status' => StateInterface::STATUS_INVALID, + ], + 'same_backorders' => [ + 'value' => Stock::BACKORDERS_YES_NONOTIFY, + 'current_value' => Stock::BACKORDERS_YES_NONOTIFY, + 'expected_indexer_status' => StateInterface::STATUS_VALID, + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php new file mode 100644 index 0000000000000..f0d87f06514f1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFilterToCollectionTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Ui\DataProvider\Product; + +use Magento\Framework\App\RequestInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks that the product quantity filter is working correctly + * + * @magentoAppArea adminhtml + */ +class AddQuantityFilterToCollectionTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var UiComponentFactory */ + private $componentFactory; + + /** @var RequestInterface */ + private $request; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->request = $this->objectManager->get(RequestInterface::class); + $this->componentFactory = $this->objectManager->get(UiComponentFactory::class); + } + + /** + * @dataProvider quantityFilterProvider + * @magentoDataFixture Magento/Catalog/_files/multiple_products.php + * @param array $filter + * @param array $expectedProducts + * @return void + */ + public function testQuantityFilter(array $filter, array $expectedProducts): void + { + $this->request->setParams([ContextInterface::FILTER_VAR => $filter]); + $dataProviderData = $this->getComponentProvidedData('product_listing'); + $actualProducts = array_column($dataProviderData['items'], 'sku'); + $this->assertEquals($expectedProducts, $actualProducts, 'Expected products do not match actual products!'); + } + + /** + * Data provider for testQuantityFilter + * + * @return array + */ + public function quantityFilterProvider(): array + { + return [ + 'from' => [ + 'filter' => [ + 'qty' => [ + 'from' => 100, + ], + ], + 'expected_products' => [ + 'simple1', + 'simple3', + ], + ], + 'to' => [ + 'filter' => [ + 'qty' => [ + 'to' => 100, + ], + ], + 'expected_products' => [ + 'simple1', + 'simple2', + ], + ], + 'both' => [ + 'filter' => [ + 'qty' => [ + 'from' => 60, + 'to' => 130, + ], + ], + 'expected_products' => [ + 'simple1', + ], + ], + ]; + } + + /** + * Call prepare method in the child components + * + * @param UiComponentInterface $component + * @return void + */ + private function prepareChildComponents(UiComponentInterface $component): void + { + foreach ($component->getChildComponents() as $child) { + $this->prepareChildComponents($child); + } + + $component->prepare(); + } + + /** + * Get component provided data + * + * @param string $namespace + * @return array + */ + private function getComponentProvidedData(string $namespace): array + { + $component = $this->componentFactory->create($namespace); + $this->prepareChildComponents($component); + + return $component->getContext()->getDataProvider()->getData(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php b/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php index 2d8cbbeedeab9..cf6287ed5b4e1 100644 --- a/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php +++ b/dev/tests/integration/testsuite/Magento/Csp/Model/Collector/ConfigCollectorTest.php @@ -62,9 +62,9 @@ private function getExpectedPolicies(): array [], true ), - 'font-src' => new FetchPolicy('font-src', false, [], [], true), + 'font-src' => new FetchPolicy('font-src', false, [], ['data'], true), 'frame-src' => new FetchPolicy('frame-src', false, [], [], true, false, false, [], [], true), - 'img-src' => new FetchPolicy('img-src', false, [], [], true), + 'img-src' => new FetchPolicy('img-src', false, [], ['data'], true), 'manifest-src' => new FetchPolicy('manifest-src', false, [], [], true), 'media-src' => new FetchPolicy('media-src', false, [], [], true), 'object-src' => new FetchPolicy('object-src', false, [], [], true), diff --git a/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php b/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php new file mode 100644 index 0000000000000..24fe443c8c796 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Customer/Ui/Component/Listing/Column/ConfirmationTest.php @@ -0,0 +1,127 @@ +<?php + +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Customer\Ui\Component\Listing\Column; + +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for \Magento\Customer\Ui\Component\Listing\Column\Confirmation. + */ +class ConfirmationTest extends TestCase +{ + /** + * Test subject. + * + * @var Confirmation + */ + private $confirmation; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->confirmation = Bootstrap::getObjectManager()->create( + Confirmation::class, + [ + 'components' => [], + 'data' => ['name' => 'confirmation'], + ] + ); + } + + /** + * Verify Confirmation::prepareDataSource() won't throw exception in case requested website doesn't exist. + * + * @param array $customerDataSource + * @param array $expectedResult + * @magentoConfigFixture base_website customer/create_account/confirm 1 + * @dataProvider customersDataProvider + * + * @return void + */ + public function testPrepareDataSource(array $customerDataSource, array $expectedResult): void + { + $result = $this->confirmation->prepareDataSource($customerDataSource); + + self::assertEquals($expectedResult, $result); + } + + /** + * CustomerDataSource data provider. + * + * @return array + */ + public function customersDataProvider(): array + { + return [ + [ + 'customerDataSource' => [ + 'data' => [ + 'items' => [ + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '1', + 'name' => 'John Doe', + 'email' => 'john.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:05:50', + 'website_id' => ['1'], + 'confirmation' => false, + 'created_in' => 'Default Store View', + ], + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '2', + 'name' => 'Jane Doe', + 'email' => 'jane.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:06:17', + 'website_id' => ['999999999'], + 'confirmation' => null, + 'created_in' => 'CustomStoreViewWhichDoesNotExistAnymore', + ], + ], + 'totalRecords' => 2, + ], + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '1', + 'name' => 'John Doe', + 'email' => 'john.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:05:50', + 'website_id' => ['1'], + 'confirmation' => __('Confirmation Required'), + 'created_in' => 'Default Store View', + ], + [ + 'id_field_name' => 'entity_id', + 'entity_id' => '2', + 'name' => 'Jane Doe', + 'email' => 'jane.doe@example.com', + 'group_id' => ['1'], + 'created_at' => '2020-12-28 07:06:17', + 'website_id' => ['999999999'], + 'confirmation' => __('Confirmed'), + 'created_in' => 'CustomStoreViewWhichDoesNotExistAnymore', + ], + ], + 'totalRecords' => 2, + ], + ], + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php new file mode 100644 index 0000000000000..a3515b07f1e0b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ConsumerTest.php @@ -0,0 +1,109 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MessageQueue\Model; + +use Magento\Framework\MessageQueue\Consumer; +use Magento\Framework\MessageQueue\ConsumerFactory; +use Magento\Framework\MessageQueue\EnvelopeFactory; +use Magento\Framework\MessageQueue\QueueInterface; +use Magento\MysqlMq\Model\QueueManagement; +use Magento\MysqlMq\Model\ResourceModel\Queue; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Tests the different cases of consumers running by Consumer processor + */ +class ConsumerTest extends TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var Consumer + */ + private $model; + + /** + * @var Queue + */ + private $queueResource; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = ObjectManager::getInstance(); + /** @var ConsumerFactory $factory */ + $factory = $this->objectManager->get(ConsumerFactory::class); + $this->model = $factory->get('demoConsumerWithConnectionException'); + $this->queueResource = $this->objectManager->get(Queue::class); + } + + /** + * Test if after connection exception and retry + * message doesn't have success status but still has status in progress + * + * @return void + */ + public function testRunWithException(): void + { + /** @var EnvelopeFactory $envelopFactory */ + $envelopFactory = $this->objectManager->get(EnvelopeFactory::class); + $messageBody = '{"name":"test"}'; + $topicName = 'demo.connection.exception'; + $queueName = 'queue-connection-exception'; + $envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => ['topic_name' => $topicName]]); + /** @var QueueInterface $queue */ + $queue = $this->objectManager->create( + \Magento\MysqlMq\Model\Driver\Queue::class, + ['queueName' => $queueName] + ); + $queue->push($envelope); + $messages = $this->queueResource->getMessages($queueName, 1); + $envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => $messages[0]]); + $this->model->process(1); + $queue->reject($envelope); + $this->model->process(1); + $message = $this->getLastMessage($queueName); + $this->assertEquals(QueueManagement::MESSAGE_STATUS_IN_PROGRESS, $message['status']); + } + + /** + * Return last message by queue name + * + * @param string $queueName + * @return array + */ + private function getLastMessage(string $queueName) + { + $connection = $this->queueResource->getConnection(); + $select = $connection->select() + ->from( + ['queue_message' => $this->queueResource->getTable('queue_message')], + [] + )->join( + ['queue_message_status' => $this->queueResource->getTable('queue_message_status')], + 'queue_message.id = queue_message_status.message_id', + [ + QueueManagement::MESSAGE_QUEUE_RELATION_ID => 'id', + QueueManagement::MESSAGE_STATUS => 'status', + ] + )->join( + ['queue' => $this->queueResource->getTable('queue')], + 'queue.id = queue_message_status.queue_id', + [QueueManagement::MESSAGE_QUEUE_NAME => 'name'] + )->where('queue.name = ?', $queueName) + ->order(['queue_message_status.id DESC']); + + return $connection->fetchRow($select); + } +} diff --git a/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php new file mode 100644 index 0000000000000..bede370db29c4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/MessageQueue/Model/ResourceModel/LockTest.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MessageQueue\Model\ResourceModel; + +use Magento\Framework\MessageQueue\LockInterface; +use Magento\TestFramework\ObjectManager; +use PHPUnit\Framework\TestCase; + +/** + * Covers Lock resource model test cases + */ +class LockTest extends TestCase +{ + public function testSaveLock() + { + $objectManager = ObjectManager::getInstance(); + /** @var Lock $resourceModel */ + $resourceModel = $objectManager->get(Lock::class); + $lock = $objectManager->create(LockInterface::class); + $resourceModel->saveLock($lock); + self::assertNotEquals(null, $lock->getId()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php new file mode 100644 index 0000000000000..e9c4900ded341 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_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\Registry; +use Magento\ProductAlert\Model\StockFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +$objectManager = Bootstrap::getObjectManager(); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer@example.com'); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$stockAlert = $stockFactory->create(); +$stockAlert->deleteCustomer((int)$customer->getId()); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php new file mode 100644 index 0000000000000..b9d4c4b81f69b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\CatalogInventory\Api\Data\StockStatusInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\ProductAlert\Model\ResourceModel\Stock as StockResource; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var StockResource $stockResource */ +$stockResource = $objectManager->get(StockResource::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); + + +$product = $productFactory->create(); +$product + ->setTypeId('simple') + ->setAttributeSetId(4) + ->setWebsiteIds([(int)$secondWebsite->getId()]) + ->setName('Simple Product2') + ->setSku('simple_on_second_website') + ->setPrice(10) + ->setMetaTitle('meta title2') + ->setMetaKeyword('meta keyword2') + ->setMetaDescription('meta description2') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['is_in_stock' => StockStatusInterface::STATUS_OUT_OF_STOCK]); + +$productRepository->save($product); + +$stockAlert = $stockFactory->create(); +$stockAlert->setCustomerId( + $customer->getId() +)->setProductId( + (int)$productRepository->get($product->getSku())->getId() +)->setWebsiteId( + (int)$secondWebsite->getId() +)->setStoreId( + (int)$storeManager->getStore('fixture_third_store')->getId() +); +$stockResource->save($stockAlert); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php new file mode 100644 index 0000000000000..0fa5f73a7927c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/stock_alert_on_second_website_rollback.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\ProductAlert\Model\ResourceModel\Stock as StockResource; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var StockResource $stockResource */ +$stockResource = $objectManager->get(StockResource::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('simple_on_second_website'); +} catch (NoSuchEntityException $e) { + //already removed +} + + +$stockAlert = $stockFactory->create(); +$stockAlert->deleteCustomer((int)$customer->getId(), (int)$secondWebsite->getId()); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance() + ->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php index 529b491269643..3567a7e00764f 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/LoadBlockTest.php @@ -231,6 +231,40 @@ public function testAddProductToOrderFromWishList(): void $this->assertCount(1, $quoteItems); } + /** + * Check that customer notification is NOT disabled after comment is updated. + * + * @return void + * @magentoDataFixture Magento/Checkout/_files/quote_with_customer_without_address.php + */ + public function testUpdateCustomerNote(): void + { + $customerNote = 'Example Comment'; + $quoteId = $this->getQuoteByReservedOrderId->execute('test_order_with_customer_without_address')->getId(); + $this->session->setQuoteId($quoteId); + $params = [ + 'json' => false, + 'block' => 'totals', + 'as_js_varname' => false, + ]; + $post = $this->hydratePost([ + 'order' => [ + 'comment' => [ + CartInterface::KEY_CUSTOMER_NOTE => $customerNote + ], + ], + ]); + $this->dispatchWitParams($params, $post); + + $quote = $this->session->getQuote(); + $this->assertEquals($customerNote, $quote->getCustomerNote()); + $this->assertTrue((bool)$quote->getCustomerNoteNotify()); + + preg_match('/id="notify_customer"(?<attributes>.*?)\/>/s', $this->getResponse()->getBody(), $matches); + $this->assertArrayHasKey('attributes', $matches); + $this->assertStringContainsString('checked="checked"', $matches['attributes']); + } + /** * Check customer quotes * diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php index 8abec6ac6d734..64d5cdb037343 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/InvoiceTest.php @@ -3,20 +3,57 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\Order; -class InvoiceTest extends \PHPUnit\Framework\TestCase +use PHPUnit\Framework\TestCase; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Sales\Model\ResourceModel\Order\Collection as OrderCollection; +use Magento\Sales\Api\InvoiceManagementInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; + +/** + * Invoice model test. + */ +class InvoiceTest extends TestCase { /** - * @var \Magento\Sales\Model\ResourceModel\Order\Collection + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var OrderCollection + */ + private $collection; + + /** + * @var InvoiceManagementInterface + */ + private $invoiceManagement; + + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + + /** + * @var SearchCriteriaBuilder */ - private $_collection; + private $searchCriteriaBuilder; + /** + * @inheritDoc + */ protected function setUp(): void { - $this->_collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - \Magento\Sales\Model\ResourceModel\Order\Collection::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->collection = $this->objectManager->create(OrderCollection::class); + $this->invoiceManagement = $this->objectManager->get(InvoiceManagementInterface::class); + $this->orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $this->searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); } /** @@ -27,9 +64,27 @@ public function testOrderTotalItemCount() $expectedResult = [['total_item_count' => 1]]; $actualResult = []; /** @var \Magento\Sales\Model\Order $order */ - foreach ($this->_collection->getItems() as $order) { + foreach ($this->collection->getItems() as $order) { $actualResult[] = ['total_item_count' => $order->getData('total_item_count')]; } $this->assertEquals($expectedResult, $actualResult); } + + /** + * Test order with exactly one configurable. + * + * @return void + * @magentoDataFixture Magento/Sales/_files/order_configurable_product.php + */ + public function testLastInvoiceWithConfigurable(): void + { + $searchCriteria = $this->searchCriteriaBuilder->addFilter('increment_id', '100000001') + ->create(); + $orders = $this->orderRepository->getList($searchCriteria); + $orders = $orders->getItems(); + $order = array_shift($orders); + $invoice = $this->invoiceManagement->prepareInvoice($order); + + self::assertEquals($invoice->isLast(), true); + } } diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php new file mode 100644 index 0000000000000..58475ea879094 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/Configurable/Listing/ConfigurableTest.php @@ -0,0 +1,104 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Block\Product\Renderer\Configurable\Listing; + +use Magento\Catalog\Api\ProductAttributeRepositoryInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Module\Manager; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\View\LayoutInterface; +use Magento\Swatches\Block\Product\Renderer\Listing\Configurable; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for configurable products options block with swatch attribute. + * + * @magentoDbIsolation enabled + * @magentoAppArea frontend + */ +class ConfigurableTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var SerializerInterface + */ + private $serializer; + + /** + * @var Configurable + */ + private $block; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var ProductAttributeRepositoryInterface + */ + private $productAttributeRepository; + + /** + * @var RequestInterface + */ + private $request; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass(): void + { + $objectManager = Bootstrap::getObjectManager(); + /** @var Manager $moduleManager */ + $moduleManager = $objectManager->get(Manager::class); + if (!$moduleManager->isEnabled('Magento_Catalog')) { + self::markTestSkipped('Magento_Catalog module disabled.'); + } + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->serializer = $this->objectManager->get(SerializerInterface::class); + $this->productAttributeRepository = $this->objectManager->get(ProductAttributeRepositoryInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Configurable::class); + $this->request = $this->objectManager->get(RequestInterface::class); + } + + /** + * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_images.php + * @return void + */ + public function testPreSelectedGalleryConfig(): void + { + $product = $this->productRepository->get('configurable'); + $this->block->setProduct($product); + $configurableAttribute = $this->productAttributeRepository->get('visual_swatch_attribute'); + $this->request->setQueryValue('visual_swatch_attribute', $configurableAttribute->getOptions()[1]->getValue()); + $jsonConfig = $this->serializer->unserialize($this->block->getJsonConfig()); + $this->assertArrayHasKey('preSelectedGallery', $jsonConfig); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['large']); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['medium']); + $this->assertStringEndsWith('/m/a/magento_image.jpg', $jsonConfig['preSelectedGallery']['small']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php index c900d276c7864..5c5b1399caed8 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Block/Product/Renderer/ConfigurableTest.php @@ -148,6 +148,31 @@ public function testGetJsonSwatchConfigUsedProductImage(): void ); } + /** + * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_visual_swatch_attribute.php + * @magentoDataFixture Magento/Catalog/_files/product_image.php + * @return void + */ + public function testGetJsonSwatchConfigUsedWithSwatchImageType(): void + { + $this->updateAttributeUseProductImageFlag(); + $this->updateProductImage('simple_option_2', '/m/a/magento_image.jpg', ['swatch_image']); + $expectedOptions = $this->getDefaultOptionsList(); + $expectedOptions['option 2']['value'] = $this->imageUrlBuilder->getUrl( + '/m/a/magento_image.jpg', + 'swatch_image_base' + ); + $expectedOptions['option 2']['thumb'] = $this->imageUrlBuilder->getUrl( + '/m/a/magento_image.jpg', + 'swatch_thumb_base' + ); + $this->assertOptionsData( + $this->serializer->unserialize($this->block->getJsonSwatchConfig()), + $expectedOptions, + ['swatch_input_type' => 'visual', 'use_product_image_for_swatch' => 1] + ); + } + /** * @magentoDataFixture Magento/Swatches/_files/configurable_product_with_visual_swatch_attribute.php * @return void @@ -223,15 +248,16 @@ private function updateAttributeUseProductImageFlag(): void * * @param string $sku * @param string $imageName + * @param array $imageRoles * @return void */ - private function updateProductImage(string $sku, string $imageName): void - { + private function updateProductImage( + string $sku, + string $imageName, + array $imageRoles = ['image', 'small_image', 'thumbnail'] + ): void { $product = $this->productRepository->get($sku); $product->setStoreId(Store::DEFAULT_STORE_ID) - ->setImage($imageName) - ->setSmallImage($imageName) - ->setThumbnail($imageName) ->setData( 'media_gallery', [ @@ -247,6 +273,10 @@ private function updateProductImage(string $sku, string $imageName): void ] ) ->setCanSaveCustomOptions(true); + foreach ($imageRoles as $role) { + $product->setData($role, $imageName); + } + $this->productResource->save($product); } } diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php new file mode 100644 index 0000000000000..f2bcbc27dc01a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductExtensionInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture( + 'Magento/Catalog/_files/product_image.php' +); +Resolver::getInstance()->requireDataFixture( + 'Magento/Swatches/_files/configurable_product_visual_swatch_attribute.php' +); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$configurableProduct = $productRepository->get('configurable'); +$children = $configurableProduct->getTypeInstance()->getUsedProducts($configurableProduct); +$images = ['magento_image.jpg', 'magento_small_image.jpg', 'magento_thumbnail.jpg']; +foreach ($children as $index => $product) { + $product->setImage('/m/a/' . $images[$index]) + ->setSmallImage('/m/a/' . $images[$index]) + ->setThumbnail('/m/a/' . $images[$index]) + ->setData('media_gallery', ['images' => [ + [ + 'file' => '/m/a/' . $images[$index], + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + 'media_type' => 'image', + ], + ]]) + ->setCanSaveCustomOptions(true) + ->save(); +} diff --git a/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php new file mode 100644 index 0000000000000..c201b258c5341 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/_files/configurable_product_with_images_rollback.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture( + 'Magento/Swatches/_files/configurable_product_visual_swatch_attribute_rollback.php' +); +Resolver::getInstance()->requireDataFixture( + 'Magento/Catalog/_files/product_image_rollback.php' +); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js index fc60fbb0bdccc..1101770b0faa2 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dynamic-rows/dynamic-rows.test.js @@ -171,5 +171,38 @@ define([ }; expect(JSON.stringify(model.labels())).toEqual(JSON.stringify(result)); }); + + it('Check _updatePagesQuantity method call.', function () { + model._updatePagesQuantity = jasmine.createSpy(); + + model.reload(); + + expect(model._updatePagesQuantity).toHaveBeenCalled(); + }); + + it('Check number of pages is updated after reloading dynamic-rows.', function () { + model.pageSize = 1; + model.relatedData = [ + { + name: 'first' + }, + { + name: 'second' + }, + { + name: 'third' + } + ]; + + model.reload(); + expect(model.pages()).toEqual(3); + + model.currentPage(3); + model.pageSize = 2; + + model.reload(); + expect(model.pages()).toEqual(2); + expect(model.currentPage()).toEqual(2); + }); }); }); diff --git a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php index 04df5fd3f3a6c..0027329e7d54c 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/Ftp.php @@ -313,9 +313,10 @@ public function chmod($filename, $mode) */ public function ls($grep = null) { - $ls = @ftp_nlist($this->_conn, '.'); + $ls = @ftp_nlist($this->_conn, '.') ?: []; $list = []; + foreach ($ls as $file) { $list[] = ['text' => $file, 'id' => $this->pwd() . '/' . $file]; } diff --git a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php index a5fe6f6c61506..64f04c62bbf64 100644 --- a/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php +++ b/lib/internal/Magento/Framework/Stdlib/Cookie/PhpCookieManager.php @@ -212,7 +212,10 @@ private function checkAbilityToSendCookie($name, $value) if ($numCookies > static::MAX_NUM_COOKIES) { $this->logger->warning( new Phrase('Unable to send the cookie. Maximum number of cookies would be exceeded.'), - array_merge($_COOKIE, ['user-agent' => $this->httpHeader->getHttpUserAgent()]) + [ + 'cookies' => $_COOKIE, + 'user-agent' => $this->httpHeader->getHttpUserAgent() + ] ); } diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php index e41cbdfe51638..87e10981c802c 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/Cookie/PhpCookieManagerTest.php @@ -565,7 +565,10 @@ public function testSetTooManyCookies() ->method('warning') ->with( new Phrase('Unable to send the cookie. Maximum number of cookies would be exceeded.'), - array_merge($_COOKIE, ['user-agent' => $userAgent]) + [ + 'cookies' => $_COOKIE, + 'user-agent' => $userAgent + ] ); $this->cookieManager->setPublicCookie( diff --git a/setup/performance-toolkit/config/di.xml b/setup/performance-toolkit/config/di.xml index 0b1175b0cd94c..a293edcb216af 100644 --- a/setup/performance-toolkit/config/di.xml +++ b/setup/performance-toolkit/config/di.xml @@ -6,4 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <preference for="Magento\Framework\Mail\TransportInterface" type="Magento\Setup\Framework\Mail\TransportInterfaceMock"/> + <preference for="Magento\Framework\Mail\Template\TransportBuilder" type="Magento\Setup\Framework\Mail\Template\TransportBuilderMock"/> </config> diff --git a/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php b/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php new file mode 100644 index 0000000000000..2791487c37ba5 --- /dev/null +++ b/setup/src/Magento/Setup/Framework/Mail/Template/TransportBuilderMock.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Setup\Framework\Mail\Template; + +use Magento\Framework\Mail\Template\TransportBuilder; +use Magento\Setup\Framework\Mail\TransportInterfaceMock; + +/** + * Mock for mail template transport builder. + */ +class TransportBuilderMock extends TransportBuilder +{ + /** + * @inheritDoc + */ + public function getTransport() + { + $this->prepareMessage(); + $this->reset(); + + return new TransportInterfaceMock($this->message); + } +} diff --git a/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php b/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php new file mode 100644 index 0000000000000..64abddc053504 --- /dev/null +++ b/setup/src/Magento/Setup/Framework/Mail/TransportInterfaceMock.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Setup\Framework\Mail; + +use Magento\Framework\Mail\EmailMessageInterface; +use Magento\Framework\Mail\TransportInterface; + +/** + * Mock for mail transport. + */ +class TransportInterfaceMock implements TransportInterface +{ + /** + * @var EmailMessageInterface|null + */ + private $message; + + /** + * @param EmailMessageInterface|null $message + */ + public function __construct($message = null) + { + $this->message = $message; + } + + /** + * @inheritDoc + */ + public function sendMessage() + { + } + + /** + * @inheritDoc + */ + public function getMessage() + { + return $this->message; + } +} From 5d84e2a8e9ebe9e39b3a7f0a88f583758ff1ce30 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Sun, 10 Jan 2021 12:29:50 +0200 Subject: [PATCH 147/242] Added AdminGoToOrderStatusPageActionGroup --- .../Test/Unit/Model/Product/TypeTest.php | 8 ++- .../Model/Product/Type/AbstractType.php | 7 ++- .../Magento/Sales/Model/RtlTextHandler.php | 2 +- .../AdminGoToOrderStatusPageActionGroup.xml | 19 +++++++ ...inCreateOrderStatusDuplicatingCodeTest.xml | 2 +- ...nCreateOrderStatusDuplicatingLabelTest.xml | 2 +- .../Mftf/Test/AdminCreateOrderStatusTest.xml | 2 +- .../AdminUnassignCustomOrderStatusTest.xml | 2 +- ...mOrderStatusNotVisibleOnStorefrontTest.xml | 8 +-- .../Test/Unit/Model/RtlTextHandlerTest.php | 1 + .../Ui/Component/Listing/Column/PriceTest.php | 52 +++++++++++++++++-- .../Ui/Component/Listing/Column/Price.php | 5 +- 12 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminGoToOrderStatusPageActionGroup.xml diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index b7041051591d8..9c4d4ce00b7c0 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -11,7 +11,6 @@ use Magento\Bundle\Model\Product\Type; use Magento\Bundle\Model\ResourceModel\BundleFactory; use Magento\Bundle\Model\ResourceModel\Option\Collection; -use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor; use Magento\Bundle\Model\ResourceModel\Selection\Collection as SelectionCollection; use Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory; use Magento\Bundle\Model\Selection; @@ -28,6 +27,7 @@ use Magento\CatalogInventory\Api\StockStateInterface; use Magento\CatalogInventory\Model\StockRegistry; use Magento\CatalogInventory\Model\StockState; +use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor; use Magento\Framework\DataObject; use Magento\Framework\EntityManager\EntityMetadataInterface; use Magento\Framework\EntityManager\MetadataPool; @@ -1548,6 +1548,10 @@ public function testPrepareForCartAdvancedSpecifyProductOptions() ->disableOriginalConstructor() ->getMock(); + $buyRequest->method('getOptions') + ->willReturn([333 => ['type' => 'image/jpeg']]); + $option->method('getId') + ->willReturn(333); $this->parentClass($group, $option, $buyRequest, $product); $product->expects($this->any()) @@ -1556,6 +1560,8 @@ public function testPrepareForCartAdvancedSpecifyProductOptions() $buyRequest->expects($this->once()) ->method('getBundleOption') ->willReturn([0, '', 'str']); + $group->expects($this->once()) + ->method('validateUserValue'); $result = $this->model->prepareForCartAdvanced($buyRequest, $product); $this->assertEquals('Please specify product option(s).', $result); diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index f90b097415661..19f6461d44b6a 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -3,7 +3,6 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types=1); namespace Magento\Catalog\Model\Product\Type; @@ -605,7 +604,11 @@ protected function _prepareOptions(\Magento\Framework\DataObject $buyRequest, $p if ($product->getSkipCheckRequiredOption() !== true) { $group->validateUserValue($optionsFromRequest); } elseif ($optionsFromRequest !== null && isset($optionsFromRequest[$option->getId()])) { - $transport->options[$option->getId()] = $optionsFromRequest[$option->getId()]; + if (is_array($optionsFromRequest[$option->getId()])) { + $group->validateUserValue($optionsFromRequest); + } else { + $transport->options[$option->getId()] = $optionsFromRequest[$option->getId()]; + } } } catch (LocalizedException $e) { diff --git a/app/code/Magento/Sales/Model/RtlTextHandler.php b/app/code/Magento/Sales/Model/RtlTextHandler.php index cfb88dc63f58b..b943320e0f897 100644 --- a/app/code/Magento/Sales/Model/RtlTextHandler.php +++ b/app/code/Magento/Sales/Model/RtlTextHandler.php @@ -48,7 +48,7 @@ public function reverseRtlText(string $string): string for ($i = 0; $i < $splitTextAmount; $i++) { if ($this->isRtlText($splitText[$i])) { - for ($j = $i + 1; $j < $splitTextAmount; $j++) { + for ($j = $i; $j < $splitTextAmount; $j++) { $tmp = $this->isRtlText($splitText[$j]) ? $this->stringUtils->strrev($splitText[$j]) : $splitText[$j]; $splitText[$j] = $this->isRtlText($splitText[$i]) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminGoToOrderStatusPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminGoToOrderStatusPageActionGroup.xml new file mode 100644 index 0000000000000..a47d9858652e9 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminGoToOrderStatusPageActionGroup.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="AdminGoToOrderStatusPageActionGroup"> + <annotations> + <description>Goes to Stores->Order Status->Order Status Page.</description> + </annotations> + + <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <waitForPageLoad stepKey="waitForPageLoaded"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml index 23dca916781f1..5c61a8b089b97 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingCodeTest.xml @@ -26,7 +26,7 @@ </after> <!-- Go to new order status page --> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill the form and validate message --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml index d3cd3e8b8549c..5fdc6c844f45e 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml @@ -26,7 +26,7 @@ </after> <!-- Go to new order status page --> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill the form and validate message --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml index a30040045a4ca..e424fa78362fc 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml @@ -26,7 +26,7 @@ </after> <!-- Go to new order status page --> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill the form and validate message --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml index 226524341efdd..0a533e7c9c767 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml @@ -25,7 +25,7 @@ </after> <!--Go to new order status page--> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!--Fill the form and validate save success message--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml index a5d210a9765ad..d4928b8c6295f 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml @@ -47,8 +47,8 @@ </after> <!-- Create order status --> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> - <waitForPageLoad stepKey="waitForOrderStatusPageLoad"/> + <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForOrderStatusPageLoad"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill form and validate message --> @@ -119,8 +119,8 @@ <see selector="{{AdminMessagesSection.success}}" userInput="We canceled 1 order(s)." stepKey="seeSuccessMessage"/> <!-- Unassign order status --> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatus"/> - <waitForPageLoad stepKey="waitForStatusPageLoad"/> + <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatus"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForStatusPageLoad"/> <actionGroup ref="FilterOrderStatusByLabelAndCodeActionGroup" stepKey="filterStatusGrid"> <argument name="statusLabel" value="{{defaultOrderStatus.label}}"/> <argument name="statusCode" value="{{defaultOrderStatus.status}}"/> diff --git a/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php b/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php index 2faeb17dc2395..1a8159dbf4cbb 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/RtlTextHandlerTest.php @@ -62,6 +62,7 @@ public function provideRtlTexts(): array ['Herr Prof. Dr. Gerald Schüler B.A.', false],//German ['نديم مقداد نعمان القحطاني', true],//Arabic ['شهاب الفرحان', true],//Arabic + ['مرحبا ماجنت اثنان', true],//Arabic ['צבר קרליבך', true],//Hebrew ['גורי מייזליש', true],//Hebrew ['اتابک بهشتی', true],//Persian diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php index 4a9061c3f3c5c..449ab230b568d 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PriceTest.php @@ -17,6 +17,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Contains tests for Price class + */ class PriceTest extends TestCase { /** @@ -34,6 +37,9 @@ class PriceTest extends TestCase */ private $storeManagerMock; + /** + * @inheritDoc + */ protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -57,12 +63,20 @@ protected function setUp(): void } /** - * @param $hasCurrency - * @param $dataSource - * @param $currencyCode + * Test for prepareDataSource method + * + * @param bool $hasCurrency + * @param array $dataSource + * @param string $currencyCode + * @param int|null $expectedStoreId * @dataProvider testPrepareDataSourceDataProvider */ - public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) + public function testPrepareDataSource( + bool $hasCurrency, + array $dataSource, + string $currencyCode, + ?int $expectedStoreId = null + ): void { $itemName = 'itemName'; $oldItemValue = 'oldItemValue'; @@ -79,6 +93,7 @@ public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) ->willReturn($currencyCode); $this->storeManagerMock->expects($hasCurrency ? $this->never() : $this->once()) ->method('getStore') + ->with($expectedStoreId) ->willReturn($store); $store->expects($hasCurrency ? $this->never() : $this->once()) ->method('getBaseCurrency') @@ -98,7 +113,12 @@ public function testPrepareDataSource($hasCurrency, $dataSource, $currencyCode) $this->assertEquals($newItemValue, $dataSource['data']['items'][0][$itemName]); } - public function testPrepareDataSourceDataProvider() + /** + * Provider for testPrepareDataSource + * + * @return array + */ + public function testPrepareDataSourceDataProvider(): array { $dataSource1 = [ 'data' => [ @@ -119,9 +139,31 @@ public function testPrepareDataSourceDataProvider() ] ] ]; + $dataSource3 = [ + 'data' => [ + 'items' => [ + [ + 'itemName' => 'oldItemValue', + 'store_id' => '2' + ] + ] + ] + ]; + $dataSource4 = [ + 'data' => [ + 'items' => [ + [ + 'itemName' => 'oldItemValue', + 'store_id' => 'abc' + ] + ] + ] + ]; return [ [true, $dataSource1, 'US'], [false, $dataSource2, 'SAR'], + [false, $dataSource3, 'SAR', 2], + [false, $dataSource4, 'SAR'], ]; } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php index 4ffb6f98447c7..cc323730f14b4 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Price.php @@ -10,6 +10,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\Pricing\PriceCurrencyInterface; @@ -77,8 +78,10 @@ public function prepareDataSource(array $dataSource) foreach ($dataSource['data']['items'] as & $item) { $currencyCode = isset($item['base_currency_code']) ? $item['base_currency_code'] : null; if (!$currencyCode) { + $storeId = isset($item['store_id']) && (int)$item['store_id'] !== 0 ? $item['store_id'] : + $this->context->getFilterParam('store_id', Store::DEFAULT_STORE_ID); $store = $this->storeManager->getStore( - $this->context->getFilterParam('store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID) + $storeId ); $currencyCode = $store->getBaseCurrency()->getCurrencyCode(); } From 0693f46deb01d05c17c1df4e7ddb4e23e02edd7f Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Sun, 10 Jan 2021 12:40:12 +0200 Subject: [PATCH 148/242] updated with AdminClickInsertWidgetActionGroup --- .../Test/CatalogProductListCheckWidgetOrderTest.xml | 2 +- .../Test/AdminAddVariableToWYSIWYGBlockTest.xml | 6 +++--- .../Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml | 13 ++++++------- ...minAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml | 5 ++--- ...AddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml | 4 ++-- ...dgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml | 4 ++-- ...idgetToWYSIWYGWithCatalogProductLinkTypeTest.xml | 6 +++--- ...idgetToWYSIWYGWithCatalogProductListTypeTest.xml | 4 ++-- ...oWYSIWYGWithRecentlyComparedProductsTypeTest.xml | 4 ++-- ...tToWYSIWYGWithRecentlyViewedProductsTypeTest.xml | 4 ++-- .../Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml | 8 ++++---- .../VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml | 6 +++--- .../Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml | 7 +++---- .../Test/Mftf/Test/NewProductsListWidgetTest.xml | 2 +- .../Test/Mftf/Test/ProductsListWidgetTest.xml | 2 +- 15 files changed, 37 insertions(+), 40 deletions(-) diff --git a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListCheckWidgetOrderTest.xml b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListCheckWidgetOrderTest.xml index 1d5e369d50e1d..062c4c398e189 100644 --- a/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListCheckWidgetOrderTest.xml +++ b/app/code/Magento/CatalogWidget/Test/Mftf/Test/CatalogProductListCheckWidgetOrderTest.xml @@ -70,7 +70,7 @@ <click selector="{{WidgetSection.Chooser}}" stepKey="clickChooser" /> <waitForElementVisible selector="{{WidgetSection.PreCreateCategory('$simplecategory.name$')}}" stepKey="waitForCategoryVisible" /> <click selector="{{WidgetSection.PreCreateCategory('$simplecategory.name$')}}" stepKey="selectCategory" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> <!--Save cms page and go to Storefront--> <actionGroup ref="SaveCmsPageActionGroup" stepKey="saveCmsPage"/> <actionGroup ref="NavigateToStorefrontForCreatedPageActionGroup" stepKey="navigateToTheStoreFront1"> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml index 963844710dd7f..71b2e7f772131 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml @@ -110,9 +110,9 @@ <waitForElementVisible selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="waitForBlockTitle" /> <click selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="selectPreCreateBlock" /> <wait time="3" stepKey="wait1" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> - <waitForPageLoad stepKey="waitForPageLoad10" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetBtn"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageLoad10"/> <waitForElementVisible selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="waitForSaveButtonVisible"/> <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandButtonMenu"/> <waitForElementVisible selector="{{CmsNewPagePageActionsSection.splitButtonMenu}}" stepKey="waitForSplitButtonMenuVisible"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml index 9e28e81c2696d..aca38e97dbe1a 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGBlockTest.xml @@ -40,9 +40,9 @@ <waitForElementVisible selector="{{WidgetSection.CMSPage}}" stepKey="waitForPageVisible" /> <click selector="{{WidgetSection.CMSPage}}" stepKey="selectPreCreateCMS" /> <waitForElementNotVisible selector="{{WidgetSection.SelectPageTitle}}" stepKey="waitForSlideOutCloses" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> - <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForSlideOutCloses1" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSlideOutCloses1"/> <click selector="{{BlockNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitButton"/> <click selector="{{BlockNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveBlock"/> <actionGroup ref="NavigateToCreatedCMSPageActionGroup" stepKey="navigateToCreatedCMSPage"> @@ -62,9 +62,9 @@ </actionGroup> <click selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="selectPreCreateBlock" /> <wait time="3" stepKey="wait1" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidgetBtn" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading2" /> - <waitForPageLoad stepKey="waitForPageLoad6" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidgetBtn"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading2"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageLoad6"/> <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandButtonMenu"/> <waitForElementVisible selector="{{CmsNewPagePageActionsSection.splitButtonMenu}}" stepKey="waitForSplitButtonMenuVisible"/> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> @@ -85,4 +85,3 @@ </after> </test> </tests> - diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml index a599d22eab298..bcb1cf2e2c3e5 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSPageLinkTypeTest.xml @@ -48,8 +48,8 @@ <click selector="{{WidgetSection.CMSPage}}" stepKey="selectPreCreateCMS" /> <waitForElementNotVisible selector="{{WidgetSection.SelectPageTitle}}" stepKey="waitForSlideOutCloses" /> <wait time="3" stepKey="waitForInsertWidgetClickable"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForSlideoutCloses" /> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> @@ -70,4 +70,3 @@ </after> </test> </tests> - diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml index 1c9d7b38a40a4..bb915ea73256d 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCMSStaticBlockTypeTest.xml @@ -51,8 +51,8 @@ <scrollTo selector="{{WidgetSection.BlockPage($$createPreReqBlock.identifier$$)}}" stepKey="scrollToBlockIdentifier" /> <click selector="{{WidgetSection.BlockPage($$createPreReqBlock.identifier$$)}}" stepKey="selectPreCreateBlock" /> <waitForElementNotVisible selector="{{WidgetSection.SelectBlockTitle}}" stepKey="waitForSlideoutCloses" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitingForLoading" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitingForLoading"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml index 4f78f6bcce5e0..e58b66f1bbb8d 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml @@ -49,8 +49,8 @@ <waitForElementVisible selector="{{WidgetSection.PreCreateCategory('$$createPreReqCategory.name$$')}}" stepKey="expandWait" /> <click selector="{{WidgetSection.PreCreateCategory('$$createPreReqCategory.name$$')}}" stepKey="selectPreCreateCategory" /> <waitForElementNotVisible selector="{{WidgetSection.SelectCategoryTitle}}" stepKey="waitForSlideoutCloses1" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForSlideOutCloses2" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSlideOutCloses2"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml index 4ee5b0d263d40..6825d4b21a089 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml @@ -55,9 +55,9 @@ <waitForLoadingMaskToDisappear stepKey="waitLoadingMask" /> <click selector="{{WidgetSection.PreCreateProduct('$$createPreReqProduct.name$$')}}" stepKey="selectPreProduct" /> <waitForElementNotVisible selector="{{WidgetSection.SelectProductTitle}}" stepKey="waitForSlideOutCloses" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitLoadingMask1" /> - <waitForPageLoad stepKey="wait6" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitLoadingMask1"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="wait6"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml index 6c36913cbb593..721b8cda325e3 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductListTypeTest.xml @@ -79,8 +79,8 @@ <click selector="{{WidgetSection.RuleParam}}" stepKey="clickRuleParam3"/> <fillField selector="{{WidgetSection.RuleParamInput('3','2')}}" userInput="1" stepKey="fillMinPrice"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForPageLoad stepKey="wait6" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="wait6"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml index 440f63403c519..2315262f69c3b 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyComparedProductsTypeTest.xml @@ -51,8 +51,8 @@ <selectOption selector="{{WidgetSection.ProductAttribute}}" userInput="Name" stepKey="selectProductAttributes" /> <selectOption selector="{{WidgetSection.ButtonToShow}}" userInput="Add to Cart" stepKey="selectBtnToShow" /> <selectOption selector="{{WidgetSection.WidgetTemplate}}" userInput="Compared Products Grid Template" stepKey="selectTemplate" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml index 226292e6cdea4..27a8b596513a7 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithRecentlyViewedProductsTypeTest.xml @@ -50,8 +50,8 @@ <selectOption selector="{{WidgetSection.ProductAttribute}}" userInput="Name" stepKey="selectProductAttributes" /> <selectOption selector="{{WidgetSection.ButtonToShow}}" userInput="Add to Cart" stepKey="selectBtnToShow" /> <selectOption selector="{{WidgetSection.WidgetTemplate}}" userInput="Viewed Products Grid Template" stepKey="selectTemplate" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> <scrollTo selector="{{CmsNewPagePageSeoSection.header}}" stepKey="scrollToSearchEngineTab" /> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="clickExpandSearchEngineOptimisation"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_defaultCmsPage.identifier}}" stepKey="fillFieldUrlKey"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml index c0e6a9cbd793d..4167c81a12fb4 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/CheckOrderOfProdsInWidgetOnCMSPageTest.xml @@ -90,8 +90,8 @@ <waitForPageLoad stepKey="waitForPageToLoadBeforeSelectingProduct2"/> <click selector="{{WidgetSection.PreCreateProduct('$$product2.name$$')}}" stepKey="selectProduct2"/> <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="applyProducts"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickOnInsertWidgetButton"/> - <waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSaveWidget1"/> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickOnInsertWidgetButton"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoadBeforeClickingOnSaveWidget1"/> <click selector="{{InsertWidgetSection.save}}" stepKey="saveWidget"/> <waitForPageLoad stepKey="waitForSaveComplete"/> <actionGroup ref="CompareTwoProductsOrder" stepKey="compareProductOrders1"> @@ -125,8 +125,8 @@ <click selector="{{WidgetSection.PreCreateProduct('$$product1.name$$')}}" stepKey="selectProduct1_1"/> <click selector="{{WidgetSection.PreCreateProduct('$$product1.name$$')}}" stepKey="selectProduct2_2"/> <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="applyProducts1"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickOnInsertWidgetButton1"/> - <waitForPageLoad stepKey="waitForPageToLoadBeforeClickingOnSaveWidget2"/> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickOnInsertWidgetButton1"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageToLoadBeforeClickingOnSaveWidget2"/> <click selector="{{InsertWidgetSection.save}}" stepKey="saveWidget1"/> <waitForPageLoad stepKey="waitForSaveComplete1"/> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml index 03e3097dbd720..c3a38470a5c8f 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/VerifyTinyMCEv4IsNativeWYSIWYGOnBlockTest.xml @@ -73,9 +73,9 @@ <scrollTo selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="scrollToBlockIdentifier" /> <click selector="{{WidgetSection.BlockPage(_defaultBlock.identifier)}}" stepKey="selectPreCreateBlock" /> <wait time="3" stepKey="wait1" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> - <waitForPageLoad stepKey="waitForPageLoad5" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForPageLoad5"/> <waitForElementVisible selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="waitForSaveButtonVisible"/> <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandButtonMenu"/> <click selector="{{CmsNewPagePageActionsSection.savePage}}" stepKey="clickSavePage"/> diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml index 0fa16d275d6f4..961c8c8cb391e 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddWidgetToWYSIWYGNewsletterTest.xml @@ -42,9 +42,9 @@ <waitForElementVisible selector="{{WidgetSection.CMSPage}}" stepKey="waitForPageVisible" /> <click selector="{{WidgetSection.CMSPage}}" stepKey="selectPreCreateCMS" /> <waitForElementNotVisible selector="{{WidgetSection.SelectPageTitle}}" stepKey="waitForSlideOutCloses" /> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget" /> - <waitForLoadingMaskToDisappear stepKey="waitForLoading" /> - <waitForElementNotVisible selector="{{WidgetSection.InsertWidgetTitle}}" stepKey="waitForSlideOutCloses1" /> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForLoading"/> + <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForSlideOutCloses1"/> <click selector="{{BasicFieldNewsletterSection.save}}" stepKey="clickSaveTemplate"/> <waitForPageLoad stepKey="waitForPageLoad10" /> <click selector="{{NewsletterWYSIWYGSection.Preview(_defaultNewsletter.name)}}" stepKey="clickPreview" /> @@ -59,4 +59,3 @@ </after> </test> </tests> - diff --git a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml index 04218c76a4b7b..be5c58f412860 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/NewProductsListWidgetTest.xml @@ -44,7 +44,7 @@ <waitForPageLoad stepKey="waitForWidgetOptions"/> <selectOption selector="{{WidgetSection.DisplayType}}" userInput="New products" stepKey="selectDisplayType"/> <fillField selector="{{WidgetSection.NoOfProductToDisplay}}" userInput="100" stepKey="fillNoOfProductToDisplay"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget"/> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> <click selector="{{CmsNewPagePageSeoSection.header}}" stepKey="expandSeoSection"/> <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{_newDefaultCmsPage.identifier}}" stepKey="fillPageUrlKey"/> <click selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="clickSaveCmsPage"/> diff --git a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml index 593b0df3f3a02..660176896950f 100644 --- a/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml +++ b/app/code/Magento/Widget/Test/Mftf/Test/ProductsListWidgetTest.xml @@ -51,7 +51,7 @@ <waitForAjaxLoad stepKey="waitForAjaxLoad"/> <click selector="{{AdminCategorySidebarTreeSection.categoryInTree($$createCategory.name$$)}}" stepKey="clickCategoryToEditInitial"/> <click selector="{{AdminNewWidgetSection.applyParameter}}" stepKey="clickApplyRuleParameter"/> - <click selector="{{WidgetSection.InsertWidget}}" stepKey="clickInsertWidget"/> + <actionGroup ref="AdminClickInsertWidgetActionGroup" stepKey="clickInsertWidget"/> <click selector="{{CmsNewPagePageActionsSection.expandSplitButton}}" stepKey="expandSplitBtn"/> <click selector="{{CmsNewPagePageActionsSection.saveAndClose}}" stepKey="clickSaveAndClose"/> <waitForPageLoad stepKey="waitForCmsList2"/> From b628917ef6386078b2c71e6ab61672433e26fc8f Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Sun, 10 Jan 2021 16:24:18 +0200 Subject: [PATCH 149/242] corrected typo --- .../Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml | 2 +- .../Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml | 2 +- .../Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml | 2 +- .../AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml index 5fdc6c844f45e..84bda226c9512 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusDuplicatingLabelTest.xml @@ -26,7 +26,7 @@ </after> <!-- Go to new order status page --> - <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill the form and validate message --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml index e424fa78362fc..f4ad885429189 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCreateOrderStatusTest.xml @@ -26,7 +26,7 @@ </after> <!-- Go to new order status page --> - <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!-- Fill the form and validate message --> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml index 0a533e7c9c767..0224bca9d96ac 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml @@ -25,7 +25,7 @@ </after> <!--Go to new order status page--> - <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> <!--Fill the form and validate save success message--> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml index d4928b8c6295f..861a5a5bf42df 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml @@ -47,7 +47,7 @@ </after> <!-- Create order status --> - <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatusPage"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForOrderStatusPageLoad"/> <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> @@ -119,7 +119,7 @@ <see selector="{{AdminMessagesSection.success}}" userInput="We canceled 1 order(s)." stepKey="seeSuccessMessage"/> <!-- Unassign order status --> - <actionGroup name="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatus"/> + <actionGroup ref="AdminGoToOrderStatusPageActionGroup" stepKey="goToOrderStatus"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForStatusPageLoad"/> <actionGroup ref="FilterOrderStatusByLabelAndCodeActionGroup" stepKey="filterStatusGrid"> <argument name="statusLabel" value="{{defaultOrderStatus.label}}"/> From 21ddf0b9e378d55f0aa7df1e0876b661ea657423 Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Mon, 11 Jan 2021 01:12:07 +0200 Subject: [PATCH 150/242] MC-24772: After choosing "Web Site" as default, where the "Store View" is disabled, the website is crashing --- .../Adminhtml/System/Store/Save.php | 36 ++++---- app/code/Magento/Backend/i18n/en_US.csv | 1 + .../Controller/Adminhtml/System/StoreTest.php | 91 +++++++++++++++++-- 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php b/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php index 8f9ff4523f4d9..8845042cb8b0a 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php @@ -7,6 +7,9 @@ namespace Magento\Backend\Controller\Adminhtml\System\Store; use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; +use Magento\Store\Model\Group as StoreGroup; +use Magento\Store\Model\Store; +use Magento\Framework\Exception\LocalizedException; /** * Class Save @@ -33,15 +36,14 @@ private function processWebsiteSave($postData) $websiteModel->setId(null); } - $groupModel = $this->_objectManager->create(\Magento\Store\Model\Group::class); + $groupModel = $this->_objectManager->create(StoreGroup::class); $groupModel->load($websiteModel->getDefaultGroupId()); - - $storeModel = $this->_objectManager->create(\Magento\Store\Model\Store::class); + $storeModel = $this->_objectManager->create(Store::class); $storeModel->load($groupModel->getDefaultStoreId()); if ($websiteModel->getIsDefault() && !$storeModel->isActive()) { - throw new \Magento\Framework\Exception\LocalizedException( - __("Please enable your Store View before using this Web Site as Default") + throw new LocalizedException( + __('Please enable your Store View before using this Web Site as Default') ); } @@ -55,13 +57,13 @@ private function processWebsiteSave($postData) * Process Store model save * * @param array $postData - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException * @return array */ private function processStoreSave($postData) { - /** @var \Magento\Store\Model\Store $storeModel */ - $storeModel = $this->_objectManager->create(\Magento\Store\Model\Store::class); + /** @var Store $storeModel */ + $storeModel = $this->_objectManager->create(Store::class); $postData['store']['name'] = $this->filterManager->removeTags($postData['store']['name']); if ($postData['store']['store_id']) { $storeModel->load($postData['store']['store_id']); @@ -71,13 +73,13 @@ private function processStoreSave($postData) $storeModel->setId(null); } $groupModel = $this->_objectManager->create( - \Magento\Store\Model\Group::class + StoreGroup::class )->load( $storeModel->getGroupId() ); $storeModel->setWebsiteId($groupModel->getWebsiteId()); if (!$storeModel->isActive() && $storeModel->isDefault()) { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('The default store cannot be disabled') ); } @@ -91,14 +93,14 @@ private function processStoreSave($postData) * Process StoreGroup model save * * @param array $postData - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException * @return array */ private function processGroupSave($postData) { $postData['group']['name'] = $this->filterManager->removeTags($postData['group']['name']); - /** @var \Magento\Store\Model\Group $groupModel */ - $groupModel = $this->_objectManager->create(\Magento\Store\Model\Group::class); + /** @var StoreGroup $groupModel */ + $groupModel = $this->_objectManager->create(StoreGroup::class); if ($postData['group']['group_id']) { $groupModel->load($postData['group']['group_id']); } @@ -107,7 +109,7 @@ private function processGroupSave($postData) $groupModel->setId(null); } if (!$this->isSelectedDefaultStoreActive($postData, $groupModel)) { - throw new \Magento\Framework\Exception\LocalizedException( + throw new LocalizedException( __('An inactive store view cannot be saved as default store view') ); } @@ -148,7 +150,7 @@ public function execute() } $redirectResult->setPath('adminhtml/*/'); return $redirectResult; - } catch (\Magento\Framework\Exception\LocalizedException $e) { + } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); $this->_getSession()->setPostData($postData); } catch (\Exception $e) { @@ -169,10 +171,10 @@ public function execute() * Verify if selected default store is active * * @param array $postData - * @param \Magento\Store\Model\Group $groupModel + * @param StoreGroup $groupModel * @return bool */ - private function isSelectedDefaultStoreActive(array $postData, \Magento\Store\Model\Group $groupModel) + private function isSelectedDefaultStoreActive(array $postData, StoreGroup $groupModel) { if (!empty($postData['group']['default_store_id'])) { $defaultStoreId = $postData['group']['default_store_id']; diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 74633141c89fe..d5870de8b7132 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -198,6 +198,7 @@ System,System "All Stores","All Stores" "You saved the website.","You saved the website." "The default store cannot be disabled","The default store cannot be disabled" +"Please enable your Store View before using this Web Site as Default","Please enable your Store View before using this Web Site as Default" "You saved the store view.","You saved the store view." "An inactive store view cannot be saved as default store view","An inactive store view cannot be saved as default store view" "You saved the store.","You saved the store." diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/System/StoreTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/System/StoreTest.php index 37c85be7d5e09..d2dd05f57d534 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/System/StoreTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/System/StoreTest.php @@ -3,13 +3,56 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Backend\Controller\Adminhtml\System; +use Magento\Store\Model\ResourceModel\Store as StoreResource; +use Magento\Store\Api\Data\StoreInterfaceFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\Framework\Data\Form\FormKey; +use Magento\Framework\Message\MessageInterface; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\App\Request\Http as HttpRequest; + /** * @magentoAppArea adminhtml */ class StoreTest extends \Magento\TestFramework\TestCase\AbstractBackendController { + /** + * @var FormKey + */ + private $formKey; + + /** + * @var StoreResource + */ + private $storeResource; + + /** + * @var StoreInterfaceFactory + */ + private $storeFactory; + + /** + * @var WebsiteRepositoryInterface + */ + private $websiteRepository; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->formKey = $this->_objectManager->get(FormKey::class); + $this->storeResource = $this->_objectManager->get(StoreResource::class); + $this->storeFactory = $this->_objectManager->get(StoreInterfaceFactory::class); + $this->websiteRepository = $this->_objectManager->get(WebsiteRepositoryInterface::class); + } + public function testIndexAction() { $this->dispatch('backend/admin/system_store/index'); @@ -67,17 +110,53 @@ public function testIndexAction() */ public function testSaveActionWithExistCode($post, $message) { - /** @var $formKey \Magento\Framework\Data\Form\FormKey */ - $formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class); - $post['form_key'] = $formKey->getFormKey(); - $this->getRequest()->setMethod('POST'); + $post['form_key'] = $this->formKey->getFormKey(); + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->getRequest()->setPostValue($post); $this->dispatch('backend/admin/system_store/save'); //Check that errors was generated and set to session $this->assertSessionMessages( $this->containsEqual($message), - \Magento\Framework\Message\MessageInterface::TYPE_ERROR, - \Magento\Framework\Message\ManagerInterface::class + MessageInterface::TYPE_ERROR, + ManagerInterface::class + ); + } + + /** + * Save action test. + * Changing of a default website when a target website doesn't have a default store view. + * + * @return void + * @magentoDataFixture Magento/Store/_files/second_website_with_store_group_and_store.php + */ + public function testSaveActionChangeDefaultWebsiteThatDoesntHaveDefaultStoreView(): void + { + $secondWebsite = $this->websiteRepository->get('test'); + // inactivate default store view of second store + $secondStore = $this->storeFactory->create(); + $this->storeResource->load($secondStore, 'fixture_second_store', 'code'); + $secondStore->setIsActive(0); + $this->storeResource->save($secondStore); + + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $this->getRequest()->setPostValue([ + 'website' => [ + 'name' => 'Test Website', + 'code' => 'test', + 'sort_order' => '0', + 'default_group_id' => $secondWebsite->getDefaultGroupId(), + 'is_default' => '1', + 'website_id' => $secondWebsite->getId(), + ], + 'store_type' => 'website', + 'store_action' => 'edit', + ],); + $this->dispatch('backend/admin/system_store/save'); + //Check that errors was generated and set to session + $this->assertSessionMessages( + $this->containsEqual('Please enable your Store View before using this Web Site as Default'), + MessageInterface::TYPE_ERROR, + ManagerInterface::class ); } From 0b0a732ab463a3bdfec044fa23bf056e562467e9 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 11 Jan 2021 11:41:09 +0200 Subject: [PATCH 151/242] MC-40149: Create automated test for: "Send request to admin/catalog/product/duplicate controller" --- .../Adminhtml/Product/DuplicateTest.php | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/DuplicateTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/DuplicateTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/DuplicateTest.php new file mode 100644 index 0000000000000..a8a4968610535 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/DuplicateTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Message\MessageInterface; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Test class for Product duplicate action + * + * @magentoAppArea adminhtml + * @see \Magento\Catalog\Controller\Adminhtml\Product\Duplicate + */ +class DuplicateTest extends AbstractBackendController +{ + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var string + */ + private $duplicatedProductSku; + + /** + * @var array + */ + private $dataKeys = ['name', 'description', 'short_description', 'price', 'weight', 'attribute_set_id']; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->productRepository = $this->_objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + try { + $this->productRepository->deleteById($this->duplicatedProductSku); + } catch (NoSuchEntityException $e) { + // product already deleted + } + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * + * @return void + */ + public function testDuplicateAction(): void + { + $product = $this->productRepository->get('simple'); + $this->getRequest()->setMethod(HttpRequest::METHOD_GET); + $this->getRequest()->setParams( + [ + 'id' => $product->getId(), + 'attribute_set_id' => $product->getAttributeSetId(), + ] + ); + $this->dispatch('backend/catalog/product/duplicate'); + $this->assertSessionMessages( + $this->containsEqual((string)__('You duplicated the product.')), + MessageInterface::TYPE_SUCCESS + ); + $this->assertRedirect($this->stringContains('catalog/product/edit/')); + $productId = $this->getIdFromRedirectedUrl(); + $this->assertNotEmpty($productId, 'Id not found'); + $duplicatedProduct = $this->productRepository->getById((int)$productId); + $this->duplicatedProductSku = $duplicatedProduct->getSku(); + $this->assertProductDuplicated($product, $duplicatedProduct); + } + + /** + * Get id value from redirected url + * + * @return string + */ + private function getIdFromRedirectedUrl(): string + { + $url = $this->getResponse() + ->getHeader('Location') + ->getFieldValue(); + $pattern = '!/id/(.*?)/!'; + $result = preg_match($pattern, $url, $matches); + + return $result ? $matches[1] : ''; + } + + /** + * Checks that duplicate product was created from the first product + * + * @param ProductInterface $product + * @param ProductInterface $duplicatedProduct + * @return void + */ + private function assertProductDuplicated(ProductInterface $product, ProductInterface $duplicatedProduct): void + { + foreach ($this->dataKeys as $key) { + $this->assertEquals($product->getData($key), $duplicatedProduct->getData($key)); + } + } +} From 26e8eee851f522be49845605fa23f8f5eb444cfa Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Mon, 11 Jan 2021 12:55:52 +0200 Subject: [PATCH 152/242] MC-35690: [B2B] Unexpected results of editing of a Bundle Product in the Shopping Cart, added from a Requisition List --- app/code/Magento/Bundle/Model/CartItemProcessor.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Bundle/Model/CartItemProcessor.php b/app/code/Magento/Bundle/Model/CartItemProcessor.php index 0a9fb6e995e5a..e5c6990574f01 100644 --- a/app/code/Magento/Bundle/Model/CartItemProcessor.php +++ b/app/code/Magento/Bundle/Model/CartItemProcessor.php @@ -83,7 +83,8 @@ public function processOptions(CartItemInterface $cartItem) } $productOptions = []; $bundleOptions = $cartItem->getBuyRequest()->getBundleOption(); - $bundleOptionsQty = $cartItem->getBuyRequest()->getBundleOptionQty() ?? []; + $bundleOptionsQty = $cartItem->getBuyRequest()->getBundleOptionQty(); + $bundleOptionsQty = is_array($bundleOptionsQty) ? $bundleOptionsQty : []; if (is_array($bundleOptions)) { foreach ($bundleOptions as $optionId => $optionSelections) { if (empty($optionSelections)) { @@ -95,7 +96,7 @@ public function processOptions(CartItemInterface $cartItem) $productOption = $this->bundleOptionFactory->create(); $productOption->setOptionId($optionId); $productOption->setOptionSelections($optionSelections); - if (is_array($bundleOptionsQty) && isset($bundleOptionsQty[$optionId])) { + if (isset($bundleOptionsQty[$optionId])) { $productOption->setOptionQty($bundleOptionsQty[$optionId]); } $productOptions[] = $productOption; From e85c550a58808b6c0c75e773ee6f1ce98d4349bb Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 11 Jan 2021 13:34:40 +0200 Subject: [PATCH 153/242] MC-38088: [MFTF] Flaky AdminSimpleProductRemoveImagesTest --- .../AdminSimpleProductRemoveImagesTest.xml | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml index e1c97b205d4fa..8b3d1a2a6ca2c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml @@ -11,11 +11,11 @@ <annotations> <features value="Catalog"/> <stories value="Add/remove images and videos for all product types and category"/> - <title value="Admin should be able to remove Product Images assigned as Base, Small and Thumbnail from Simple Product"/> + <title value="Remove Product Images assigned as Base, Small and Thumbnail from Simple Product"/> <description value="Admin should be able to remove Product Images assigned as Base, Small and Thumbnail from Simple Product"/> - <severity value="BLOCKER"/> - <testCaseId value="MC-191"/> - <group value="Catalog"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-25383"/> + <group value="catalog"/> </annotations> <before> @@ -29,6 +29,8 @@ <after> <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> + <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductsPage"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> @@ -36,16 +38,16 @@ <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductIndex"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGrid"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProductGridBySku"> - <argument name="product" value="$$product$$"/> + <argument name="product" value="$product$"/> </actionGroup> - <actionGroup ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup" stepKey="openProduct"/> + <actionGroup ref="AdminProductGridSectionClickFirstRowActionGroup" stepKey="openProduct"/> <!-- Set url key --> - <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="openSeoSection"/> - <fillField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="$$product.name$$" stepKey="fillUrlKey"/> + <comment userInput="BIC workaround" stepKey="openSeoSection"/> + <comment userInput="BIC workaround" stepKey="fillUrlKey"/> <!-- Expand images section --> - <click selector="{{AdminProductImagesSection.productImagesToggle}}" stepKey="expandImages"/> + <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages"/> <!-- Upload and set Base image --> <attachFile selector="{{AdminProductImagesSection.imageFileUpload}}" userInput="adobe-base.jpg" stepKey="attach1"/> @@ -87,12 +89,12 @@ <actionGroup ref="AdminProductFormSaveActionGroup" stepKey="saveProduct"/> <!-- Go to the product page and see the Base image --> - <amOnPage url="$$product.name$$.html" stepKey="goToProductPage"/> + <amOnPage url="{{StorefrontProductPage.url($product.custom_attributes[url_key]$)}}" stepKey="goToProductPage"/> <waitForPageLoad stepKey="wait4"/> <seeElement selector="{{StorefrontProductMediaSection.imageFile('/adobe-base')}}" stepKey="seeBase"/> <!-- Go to the category page and see the Small image --> - <amOnPage url="$$category.name$$.html" stepKey="goToCategoryPage"/> + <amOnPage url="{{StorefrontCategoryPage.url($category.custom_attributes[url_key]$)}}" stepKey="goToCategoryPage"/> <waitForPageLoad stepKey="wait3"/> <seeElement selector="{{StorefrontCategoryProductSection.ProductImageBySrc('/adobe-small')}}" stepKey="seeThumb"/> @@ -100,7 +102,7 @@ <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductIndex2"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGrid2"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProductGridBySku2"> - <argument name="product" value="$$product$$"/> + <argument name="product" value="$product$"/> </actionGroup> <seeElement selector="{{AdminProductGridSection.productThumbnailBySrc('/adobe-thumb')}}" stepKey="seeBaseInGrid"/> @@ -108,10 +110,10 @@ <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductIndex3"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGrid3"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProductGridBySku3"> - <argument name="product" value="$$product$$"/> + <argument name="product" value="$product$"/> </actionGroup> - <actionGroup ref="OpenProductForEditByClickingRowXColumnYInProductGridActionGroup" stepKey="openProduct3"/> - <click selector="{{AdminProductImagesSection.productImagesToggle}}" stepKey="expandImages2"/> + <actionGroup ref="AdminProductGridSectionClickFirstRowActionGroup" stepKey="openProduct3"/> + <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages2"/> <!-- Remove all images --> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('1')}}" stepKey="removeImage1"/> @@ -123,19 +125,19 @@ <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductIndex4"/> <actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGrid4"/> <actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterProductGridBySku4"> - <argument name="product" value="$$product$$"/> + <argument name="product" value="$product$"/> </actionGroup> <dontSeeElement selector="{{AdminProductGridSection.productThumbnailBySrc('/adobe-thumb')}}" stepKey="dontSeeBaseInGrid"/> <seeElement selector="{{AdminProductGridSection.productThumbnailBySrc('/placeholder/thumbnail')}}" stepKey="seePlaceholderThumb"/> <!-- Check category page for placeholder --> - <amOnPage url="$$category.name$$.html" stepKey="goToCategoryPage2"/> + <amOnPage url="{{StorefrontCategoryPage.url($category.custom_attributes[url_key]$)}}" stepKey="goToCategoryPage2"/> <waitForPageLoad stepKey="wait7"/> <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductImageBySrc('/adobe-small')}}" stepKey="dontSeeThumb"/> <seeElement selector="{{StorefrontCategoryProductSection.ProductImageBySrc('placeholder/small_image')}}" stepKey="seePlaceholderSmall"/> <!-- Check product page for placeholder --> - <amOnPage url="$$product.name$$.html" stepKey="goToProductPage2"/> + <amOnPage url="{{StorefrontProductPage.url($product.custom_attributes[url_key]$)}}" stepKey="goToProductPage2"/> <waitForPageLoad stepKey="wait8"/> <dontSeeElement selector="{{StorefrontProductMediaSection.imageFile('/adobe-base')}}" stepKey="dontSeeBase"/> <seeElement selector="{{StorefrontProductMediaSection.imageFile('placeholder/image')}}" stepKey="seePlaceholderBase"/> From be95b7f596f1f81313df93f14e57631776c9b9a0 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 11 Jan 2021 13:48:05 +0200 Subject: [PATCH 154/242] MC-40085: Create automated test for: "Try to change category design by restricted admin" --- .../Model/Category/AuthorizationMock.php | 22 +++++ .../Model/Category/AuthorizationTest.php | 99 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationMock.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationMock.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationMock.php new file mode 100644 index 0000000000000..7e4142b199f42 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationMock.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Category; + +/** + * Mock for authorization process + */ +class AuthorizationMock extends \Magento\Framework\Authorization +{ + /** + * @inheritdoc + */ + public function isAllowed($resource, $privilege = null) + { + return false; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php new file mode 100644 index 0000000000000..7583eecc065a7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Category; + +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Api\Data\CategoryInterfaceFactory; +use Magento\Catalog\Model\Category\Authorization as CategoryAuthorization; +use Magento\Framework\Authorization; +use Magento\Framework\Exception\AuthorizationException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Checks authorization for category design attributes edit + * + * @magentoDbIsolation enabled + */ +class AuthorizationTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var CategoryAuthorization */ + private $model; + + /** @var CategoryInterfaceFactory */ + private $categoryFactory; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->objectManager->addSharedInstance( + $this->objectManager->get(AuthorizationMock::class), + Authorization::class + ); + $this->model = $this->objectManager->get(CategoryAuthorization::class); + $this->categoryFactory = $this->objectManager->get(CategoryInterfaceFactory::class); + } + + /** + * @inheritdoc + */ + protected function tearDown(): void + { + $this->objectManager->removeSharedInstance(Authorization::class); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/category.php + * + * @return void + */ + public function testAuthorizationWit(): void + { + $category = $this->createCategoryWithData(['entity_id' => 333, 'custom_use_parent_settings' => true]); + $this->expectException(AuthorizationException::class); + $this->expectExceptionMessage((string)__('Not allowed to edit the category\'s design attributes')); + $this->model->authorizeSavingOf($category); + } + + /** + * @return void + */ + public function testWithWrongCategoryId(): void + { + $wrongCategoryId = 56464654; + $category = $this->createCategoryWithData(['entity_id' => $wrongCategoryId]); + $this->expectExceptionObject(NoSuchEntityException::singleField('id', $wrongCategoryId)); + $this->model->authorizeSavingOf($category); + } + + /** + * Create category instance with provided data + * + * @param array $data + * @return CategoryInterface + */ + private function createCategoryWithData(array $data): CategoryInterface + { + $category = $this->categoryFactory->create(); + $category->addData($data); + + return $category; + } +} From 64bf6ce11150149f394d1c79295c41c58261fc80 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Mon, 11 Jan 2021 14:11:30 +0200 Subject: [PATCH 155/242] MC-38423: Some Elements of the Shopping Cart page are overlapped with certain view --- .../Checkout/view/frontend/templates/cart/item/default.phtml | 4 ---- .../frontend/Magento/blank/web/css/source/_extends.less | 1 + app/design/frontend/Magento/luma/web/css/source/_extends.less | 1 + 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml index 6937bb54baa08..c3bddbac56487 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml @@ -48,12 +48,8 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <dt><?= $block->escapeHtml($_option['label']) ?></dt> <dd> <?php if (isset($_formatedOptionValue['full_view'])) :?> - <?php if (strlen($_formatedOptionValue['full_view']) <= 100) :?> <?= $block->escapeHtml($_formatedOptionValue['full_view']) ?> <?php else :?> - <?= $block->escapeHtml($_formatedOptionValue['value'], ['span', 'a']) ?> - <?php endif; ?> - <?php else :?> <?= $block->escapeHtml($_formatedOptionValue['value'], ['span', 'a']) ?> <?php endif; ?> </dd> diff --git a/app/design/frontend/Magento/blank/web/css/source/_extends.less b/app/design/frontend/Magento/blank/web/css/source/_extends.less index 690b89f42b419..32e18921a1c48 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_extends.less +++ b/app/design/frontend/Magento/blank/web/css/source/_extends.less @@ -51,6 +51,7 @@ display: inline-block; float: left; margin: 0 0 @indent__xs; + word-break: break-all; } }; diff --git a/app/design/frontend/Magento/luma/web/css/source/_extends.less b/app/design/frontend/Magento/luma/web/css/source/_extends.less index 8ae1776daf239..4d5e6f55908da 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_extends.less +++ b/app/design/frontend/Magento/luma/web/css/source/_extends.less @@ -127,6 +127,7 @@ display: inline-block; float: left; margin: 0 0 @indent__xs; + word-break: break-all; } }; From 1746104147a530c2eb3940c929685d7a4c1a0690 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Mon, 11 Jan 2021 14:46:59 +0200 Subject: [PATCH 156/242] MC-40148: Create automated test for: "Set decimal Qty increment" --- .../Model/System/Config/Backend/QtyincrementsTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php index 8fcec1c02670d..168079ce3c2cb 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/System/Config/Backend/QtyincrementsTest.php @@ -52,7 +52,9 @@ protected function setUp(): void public function testAfterSaveWithDecimals(): void { $this->expectException(LocalizedException::class); - $this->expectExceptionMessage((string)__("Quantity increments can't use decimals. Enter a new increment and try again.")); + $this->expectExceptionMessage( + (string)__("Quantity increments can't use decimals. Enter a new increment and try again.") + ); $value = 10.5; $this->qtyIncrements->setValue((string)$value); $this->qtyIncrements->beforeSave(); From 53b893f1775049b7e0bd96c01ee47eecfa1a335d Mon Sep 17 00:00:00 2001 From: engcom-Kilo <mikola.malevanec@transoftgroup.com> Date: Tue, 5 Jan 2021 13:51:43 +0200 Subject: [PATCH 157/242] MC-23729: Invalid date when timeOnly defined on datetime UIComponent. --- .../Ui/view/base/web/js/form/element/date.js | 23 ++++++++++++------- .../js/lib/knockout/bindings/datepicker.js | 6 +++-- .../Ui/base/js/form/element/date.test.js | 17 ++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js index af9142745206b..9e071e72ca8b7 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js @@ -124,7 +124,7 @@ define([ var shiftedValue; if (value) { - if (this.options.showsTime) { + if (this.options.showsTime && !this.options.timeOnly) { shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone); } else { shiftedValue = moment(value, this.outputDateFormat, true); @@ -157,7 +157,7 @@ define([ if (shiftedValue) { momentValue = moment(shiftedValue, this.pickerDateTimeFormat); - if (this.options.showsTime) { + if (this.options.showsTime && !this.options.timeOnly) { formattedValue = moment(momentValue).format(this.timezoneFormat); value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString(); } else { @@ -177,10 +177,13 @@ define([ * with moment.js library. */ prepareDateTimeFormats: function () { - this.pickerDateTimeFormat = this.options.dateFormat; - - if (this.options.showsTime) { - this.pickerDateTimeFormat += ' ' + this.options.timeFormat; + if (this.options.timeOnly) { + this.pickerDateTimeFormat = this.options.timeFormat; + } else { + this.pickerDateTimeFormat = this.options.dateFormat; + if (this.options.showsTime) { + this.pickerDateTimeFormat += ' ' + this.options.timeFormat; + } } this.pickerDateTimeFormat = utils.convertToMomentFormat(this.pickerDateTimeFormat); @@ -189,8 +192,12 @@ define([ this.outputDateFormat = this.options.dateFormat; } - this.inputDateFormat = utils.convertToMomentFormat(this.inputDateFormat); - this.outputDateFormat = utils.convertToMomentFormat(this.outputDateFormat); + this.inputDateFormat = this.options.timeOnly ? + utils.convertToMomentFormat(this.pickerDefaultTimeFormat) : + utils.convertToMomentFormat(this.inputDateFormat); + this.outputDateFormat = this.options.timeOnly ? + utils.convertToMomentFormat(this.options.timeFormat) : + utils.convertToMomentFormat(this.outputDateFormat); this.validationParams.dateFormat = this.outputDateFormat; } diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js index 284d395d8120b..ff09835df61f3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js @@ -87,8 +87,10 @@ define([ ).toDate(); } - $element.datepicker('setDate', newVal); - $element.blur(); + if (!options.timeOnly) { + $element.datepicker('setDate', newVal); + $element.blur(); + } }); } }; diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js index 91f37e20cca87..a70eef170a4ea 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js @@ -65,5 +65,22 @@ define([ expect(model.getPreview()).toBe('28-11-2020'); }); + it('Check date will have correct value with timeOnly config value.', function () { + model.options.timeOnly = true; + model.options.timeFormat = 'h:mm a'; + model.prepareDateTimeFormats(); + model.value('02:43:58'); + expect(model.getPreview()).toBe('2:43 am'); + + model.options.timeFormat = 'HH:mm:ss'; + model.prepareDateTimeFormats(); + model.value('02:43:58'); + expect(model.getPreview()).toBe('02:43:58'); + + model.options.timeFormat = 'HH:mm:ss'; + model.prepareDateTimeFormats(); + model.value('2:43 am'); + expect(model.getPreview()).toBe('02:43:00'); + }); }); }); From 2dd3d56b134246731bfe23dc01e46cb9cd865426 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Mon, 11 Jan 2021 15:38:20 +0200 Subject: [PATCH 158/242] MC-39551: Create automated test for: "On category page switch to list mode" --- .../Block/Product/ProductList/ToolbarTest.php | 98 ++++++++++++------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php index 392e77d60d3e3..dc4cede166a83 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/ProductList/ToolbarTest.php @@ -20,30 +20,46 @@ * @see \Magento\Catalog\Block\Product\ProductList\Toolbar * @magentoAppArea frontend * @magentoDbIsolation enabled - * @magentoAppIsolation enabled */ class ToolbarTest extends TestCase { + /** @var string */ + private const XPATH_TEMPLATE_FOR_NOT_VISIBLE_ICON_CASES = '//div[contains(@class, "modes")]/*[@data-value="%s"]'; + + /** @var string */ + private const ACTIVE_MODE_XPATH_TEMPLATE = + '//div[contains(@class, "modes")]/strong[@data-value="%s" and contains(@class, "active")]'; + + /** @var string */ + private const NOT_ACTIVE_MODE_XPATH_TEMPLATE = '//div[contains(@class, "modes")]/a[@data-value="%s"]'; + /** @var ObjectManagerInterface */ private $objectManager; /** @var LayoutInterface */ private $layout; + /** @var Toolbar */ + private $toolbarBlock; + /** * @inheritdoc */ protected function setUp(): void { parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); $this->layout = $this->objectManager->get(LayoutInterface::class); + $this->toolbarBlock = $this->layout->createBlock(Toolbar::class); } - public function testGetPagerHtml() + /** + * @return void + */ + public function testGetPagerHtml(): void { - /** @var $block Toolbar */ - $block = $this->layout->createBlock(Toolbar::class, 'block'); + $this->toolbarBlock->setNameInLayout('block'); /** @var $childBlock Text */ $childBlock = $this->layout->addBlock( Text::class, @@ -51,100 +67,114 @@ public function testGetPagerHtml() 'block' ); $expectedHtml = '<b>Any text there</b>'; - $this->assertNotEquals($expectedHtml, $block->getPagerHtml()); + $this->assertNotEquals($expectedHtml, $this->toolbarBlock->getPagerHtml()); $childBlock->setText($expectedHtml); - $this->assertEquals($expectedHtml, $block->getPagerHtml()); + $this->assertEquals($expectedHtml, $this->toolbarBlock->getPagerHtml()); } /** - * @magentoConfigFixture default_store catalog/frontend/list_mode grid + * @magentoConfigFixture current_store catalog/frontend/list_mode grid + * @return void */ public function testToHtmlGridOnly(): void { - $block = $this->layout->createBlock(Toolbar::class, 'block'); - $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $htmlOutput = $this->getModeSwitcherHtml(); + $this->assertNotEmpty($htmlOutput); $this->assertEquals( 0, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/*[@data-value="grid"]', - $block->toHtml() + sprintf(self::XPATH_TEMPLATE_FOR_NOT_VISIBLE_ICON_CASES, 'grid'), + $htmlOutput ) ); $this->assertEquals( 0, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/*[@data-value="list"]', - $block->toHtml() + sprintf(self::XPATH_TEMPLATE_FOR_NOT_VISIBLE_ICON_CASES, 'list'), + $htmlOutput ) ); } /** - * @magentoConfigFixture default_store catalog/frontend/list_mode list + * @magentoConfigFixture current_store catalog/frontend/list_mode list + * @return void */ public function testToHtmlListOnly(): void { - $block = $this->layout->createBlock(Toolbar::class, 'block'); - $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $htmlOutput = $this->getModeSwitcherHtml(); + $this->assertNotEmpty($htmlOutput); $this->assertEquals( 0, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/*[@data-value="grid"]', - $block->toHtml() + sprintf(self::XPATH_TEMPLATE_FOR_NOT_VISIBLE_ICON_CASES, 'grid'), + $htmlOutput ) ); $this->assertEquals( 0, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/*[@data-value="list"]', - $block->toHtml() + sprintf(self::XPATH_TEMPLATE_FOR_NOT_VISIBLE_ICON_CASES, 'list'), + $htmlOutput ) ); } /** - * @magentoConfigFixture default_store catalog/frontend/list_mode grid-list + * @magentoConfigFixture current_store catalog/frontend/list_mode grid-list + * @return void */ public function testToHtmlGridList(): void { - $block = $this->layout->createBlock(Toolbar::class, 'block'); - $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $htmlOutput = $this->getModeSwitcherHtml(); $this->assertEquals( 1, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/strong[@data-value="grid" and contains(@class, "active")]', - $block->toHtml() + sprintf(self::ACTIVE_MODE_XPATH_TEMPLATE, 'grid'), + $htmlOutput ) ); $this->assertEquals( 1, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/a[@data-value="list"]', - $block->toHtml() + sprintf(self::NOT_ACTIVE_MODE_XPATH_TEMPLATE, 'list'), + $htmlOutput ) ); } /** - * @magentoConfigFixture default_store catalog/frontend/list_mode list-grid + * @magentoConfigFixture current_store catalog/frontend/list_mode list-grid + * @return void */ public function testToHtmlListGrid(): void { - $block = $this->layout->createBlock(Toolbar::class, 'block'); - $block->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + $htmlOutput = $this->getModeSwitcherHtml(); $this->assertEquals( 1, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/strong[@data-value="list" and contains(@class, "active")]', - $block->toHtml() + sprintf(self::ACTIVE_MODE_XPATH_TEMPLATE, 'list'), + $htmlOutput ) ); $this->assertEquals( 1, Xpath::getElementsCountForXpath( - '//div[contains(@class, "modes")]/a[@data-value="grid"]', - $block->toHtml() + sprintf(self::NOT_ACTIVE_MODE_XPATH_TEMPLATE, 'grid'), + $htmlOutput ) ); } + + /** + * Mode switcher html + * + * @return string + */ + private function getModeSwitcherHtml(): string + { + $this->toolbarBlock->setTemplate('Magento_Catalog::product/list/toolbar/viewmode.phtml'); + + return $this->toolbarBlock->toHtml(); + } } From 73dc5381044021596dc68b467755d71b9d35b770 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Mon, 11 Jan 2021 16:46:41 +0200 Subject: [PATCH 159/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- .../view/frontend/web/js/fotorama-add-video-events.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js index acaf2afeb6c26..bfd685543d7f7 100644 --- a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js +++ b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js @@ -714,6 +714,7 @@ define([ } $('.' + this.FTAR).addClass(this.isFullscreen ? 'fotorama__arr--shown' : 'fotorama__arr--hidden'); + $('.' + this.FTVC).addClass('fotorama-show-control'); } }, From 4f4b98aed68992d1c1ae3850274ebf877bd6fcb8 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 20:58:39 +0530 Subject: [PATCH 160/242] Update README.md --- app/code/Magento/WebapiAsync/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/WebapiAsync/README.md b/app/code/Magento/WebapiAsync/README.md index 36b092c938fa3..f24ec19b3eb3b 100644 --- a/app/code/Magento/WebapiAsync/README.md +++ b/app/code/Magento/WebapiAsync/README.md @@ -1,25 +1,25 @@ # Magento_WebapiAsync module -**Magento_WebapiAsync** module extends Webapi extension and provide functional to process asynchronous requests. +Magento_WebapiAsync module extends Webapi extension and provide functional to process asynchronous requests. -**Magento_WebapiAsync** module handles asynchronous requests, schedule, publish and consume bulk operations from a queue. +Magento_WebapiAsync module handles asynchronous requests, schedule, publish and consume bulk operations from a queue. ## Installation details -Before installing this module, note that the **Magento_WebapiAsync** is dependent on the following modules: +Before installing this module, note that the Magento_WebapiAsync is dependent on the following modules: - Magento_AsynchronousOperations - Magento_Customer - Magento_User - Magento_Webapi -Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Structure `Code/` - the directory that contains Remote service reader configuration files. -For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility From 54d95d0dd537d03777677d608b46d0f44a99d606 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 20:59:15 +0530 Subject: [PATCH 161/242] Update README.md --- app/code/Magento/WebapiSecurity/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/WebapiSecurity/README.md b/app/code/Magento/WebapiSecurity/README.md index 954ec10d3dc60..61bf8fd1cd1e3 100644 --- a/app/code/Magento/WebapiSecurity/README.md +++ b/app/code/Magento/WebapiSecurity/README.md @@ -1,6 +1,6 @@ # Magento_WebapiSecurity module -The **Magento_WebapiSecurity** module enables access management of some Web API resources. +The Magento_WebapiSecurity module enables access management of some Web API resources. If checkbox enabled in backend through: `Stores -> Configuration -> Services -> Magento Web API -> Web Api Security` then the security of all the services outlined in `app/code/Magento/WebapiSecurity/etc/di.xml` would be loosened. You may modify this list to customize which services should follow this behavior. @@ -8,8 +8,8 @@ By loosening the security, these services would allow access anonymously (by any ## Installation details -Before installing this module, note that the **Magento_WebapiSecurity** is dependent on the following modules: +Before installing this module, note that the Magento_WebapiSecurity is dependent on the following modules: - `Magento_Webapi` -Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). From 447f3c6cae9e9d1b4b97b5850d138bf6e0b02723 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:00:38 +0530 Subject: [PATCH 162/242] Update README.md --- app/code/Magento/Weee/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Weee/README.md b/app/code/Magento/Weee/README.md index 0e846694523a9..516f442d23315 100644 --- a/app/code/Magento/Weee/README.md +++ b/app/code/Magento/Weee/README.md @@ -1,12 +1,12 @@ # Magento_Weee module -The **Magento_Weee** module enables the application of fees/fixed product taxes (FPT) on certain types of products, usually related to electronic devices and recycling. +The Magento_Weee module enables the application of fees/fixed product taxes (FPT) on certain types of products, usually related to electronic devices and recycling. Fixed product taxes can be used to setup a WEEE tax that is a fixed amount, rather than a percentage of the product price. FPT can be configured to be displayed at various places in Magento. Rules, amounts, and display options can be configured in the backend. -This module extends the existing functionality of **Magento_Tax**. +This module extends the existing functionality of Magento_Tax. -The **Magento_Weee** module includes the following: +The Magento_Weee module includes the following: - Ability to add different number of fixed product taxes to product. They are treated as a product attribute. - Configuration of where WEEE appears (on category, product, sales, invoice, or credit memo pages) and whether FPT should be taxed. @@ -14,9 +14,9 @@ The **Magento_Weee** module includes the following: ## Installation details -The **Magento_Weee** module can be installed automatically (using native Magento install mechanism) without any additional actions. +The Magento_Weee module can be installed automatically (using native Magento install mechanism) without any additional actions. -Before installing this module, note that the **Magento_Weee** is dependent on the following modules: +Before installing this module, note that the Magento_Weee is dependent on the following modules: - Magento_Catalog - Magento_Checkout @@ -26,19 +26,19 @@ Before installing this module, note that the **Magento_Weee** is dependent on th - Magento_Store - Magento_Tax -Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Structure `Pricing/` - directory that contain tax adjustment. -For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility -Extension developers can interact with the **Magento_Weee** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the Magento_Weee module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Weee** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_Weee module. ### Layouts @@ -84,7 +84,7 @@ This module introduces the following layouts and layout handles in the directori - `sales_order_printinvoice` - `sales_order_view` -For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). ### UI components @@ -96,4 +96,4 @@ You can extend a customer form and widgets using the configuration files located - `widget_recently_compared` - `widget_recently_viewed` -For information about a UI component in Magento 2, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). +For information about a UI component, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). From f5fde08d6962184cea558ce97f06dacb767aebf5 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:01:28 +0530 Subject: [PATCH 163/242] Update README.md --- app/code/Magento/WeeeGraphQl/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/WeeeGraphQl/README.md b/app/code/Magento/WeeeGraphQl/README.md index 81ee1236f00a2..b1f44619785c4 100644 --- a/app/code/Magento/WeeeGraphQl/README.md +++ b/app/code/Magento/WeeeGraphQl/README.md @@ -1,22 +1,22 @@ # Magento_WeeeGraphQl module -The **Magento_WeeeGraphQl** module provides type information for the GraphQl module to generate wee tax fields for the catalog and product information endpoints. +The Magento_WeeeGraphQl module provides type information for the GraphQl module to generate wee tax fields for the catalog and product information endpoints. -The **Magento_WeeeGraphQl** module extends **Magento_GraphQl** and **Magento_Weee** modules. This module provides type and resolver information for GraphQL API. +The Magento_WeeeGraphQl module extends Magento_GraphQl and Magento_Weee modules. This module provides type and resolver information for GraphQL API. ## Installation details -Before installing this module, note that the **Magento_WeeeGraphQl** is dependent on the following modules: +Before installing this module, note that the Magento_WeeeGraphQl is dependent on the following modules: - `Magento_CatalogGraphQl` - `Magento_Store` - `Magento_Tax` - `Magento_Weee` -For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +For information about enabling or disabling a module, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Extensibility -Extension developers can interact with the **Magento_WeeeGraphQl** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the Magento_WeeeGraphQl module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_WeeeGraphQl** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_WeeeGraphQl module. From 7728961a7d8a5dee0ce6f3567e3f6dd768ade793 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:02:27 +0530 Subject: [PATCH 164/242] Update README.md --- app/code/Magento/Widget/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Widget/README.md b/app/code/Magento/Widget/README.md index 8c06ee4c30fa9..0d51c6732ec58 100644 --- a/app/code/Magento/Widget/README.md +++ b/app/code/Magento/Widget/README.md @@ -1,28 +1,28 @@ # Magento_Widget module -The **Magento_Widget** module allows Magento application to be extended with custom widget blocks. +The Magento_Widget module allows Magento application to be extended with custom widget blocks. ## Installation details -Before installing this module, note that the **Magento_Widget** is dependent on the following modules: +Before installing this module, note that the Magento_Widget is dependent on the following modules: - Magento_Catalog - Magento_Cms - Magento_Store -Before disabling or uninstalling this module, please consider the following dependencies: +Before disabling or uninstalling this module, note the following dependencies: - Magento_CatalogWidget - Magento_CurrencySymbol - Magento_Newsletter -Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Extensibility -Extension developers can interact with the **Magento_Widget** module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). +Extension developers can interact with the Magento_Widget module. For more information about the Magento extension mechanism, see [Magento plug-ins](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html). -[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the **Magento_Widget** module. +[The Magento dependency injection mechanism](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/depend-inj.html) enables you to override the functionality of the Magento_Widget module. ### Layouts @@ -38,4 +38,4 @@ This module introduces the following layouts and layout handles in the directori - `default` - `print` -For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). From 354d3f6c07ee7f192ae14a3d40b1507045f045b6 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:03:31 +0530 Subject: [PATCH 165/242] Update README.md --- app/code/Magento/Wishlist/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Wishlist/README.md b/app/code/Magento/Wishlist/README.md index 66e0d90d5f0b2..fef81ccacf000 100644 --- a/app/code/Magento/Wishlist/README.md +++ b/app/code/Magento/Wishlist/README.md @@ -1,28 +1,28 @@ # Magento_Wishlist module -The **Magento_Wishlist** module implements the Wishlist functionality. +The Magento_Wishlist module implements the Wishlist functionality. This module allows customers to create a list of products that they can add to their shopping cart to be purchased at a later date, or share with friends. ## Installation details -Before installing this module, note that the **Magento_Wishlist** is dependent on the following modules: +Before installing this module, note that the Magento_Wishlist is dependent on the following modules: - Magento_Captcha - Magento_Catalog - Magento_Customer -Before disabling or uninstalling this module, please consider the following dependencies: +Before disabling or uninstalling this module, note the following dependencies: - Magento_WishlistAnalytics -Please find here [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Structure `Pricing/` - the directory that contain solutions for configurable and downloadable product price. -For information about a typical file structure of a module in Magento 2, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). +For information about a typical file structure of a module, see [Module file structure](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/build/module-file-structure.html#module-file-structure). ## Extensibility @@ -56,7 +56,7 @@ The module dispatches the following events: - `product` is a product object (`\Magento\Catalog\Api\Data\ProductInterface` class). - `item` is an item object (`\Magento\Wishlist\Model\Item` class). -For information about the event system in Magento 2, see [Events and observers](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/events-and-observers.html#events). +For information about the event, see [Events and observers](https://devdocs.magento.com/guides/v2.4/extension-dev-guide/events-and-observers.html#events). ### Layouts @@ -86,7 +86,7 @@ This module introduces the following layouts and layout handles in the directori - `wishlist_index_share` - `wishlist_shared_index.xml` -For more information about a layout in Magento 2, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). +For more information about a layout, see the [Layout documentation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/layouts/layout-overview.html). ### UI components @@ -97,4 +97,4 @@ You can extend a customer form and widgets using the configuration files located - `widget_recently_compared` - `widget_recently_viewed` -For information about a UI component in Magento 2, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). +For information about a UI component, see [Overview of UI components](https://devdocs.magento.com/guides/v2.4/ui_comp_guide/bk-ui_comps.html). From 6c1e76eece3b822165a87e20bdf177c68a8f0612 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:03:59 +0530 Subject: [PATCH 166/242] Update README.md --- app/code/Magento/WishlistAnalytics/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/WishlistAnalytics/README.md b/app/code/Magento/WishlistAnalytics/README.md index 5bbd19416ac82..c932397e0803a 100644 --- a/app/code/Magento/WishlistAnalytics/README.md +++ b/app/code/Magento/WishlistAnalytics/README.md @@ -1,12 +1,12 @@ # Magento_WishlistAnalytics module -The **Magento_WishlistAnalytics** module configures data definitions for a data collection related to the Wishlist module entities to be used in [Advanced Reporting](https://devdocs.magento.com/guides/v2.4/advanced-reporting/modules.html). +The Magento_WishlistAnalytics module configures data definitions for a data collection related to the Wishlist module entities to be used in [Advanced Reporting](https://devdocs.magento.com/guides/v2.4/advanced-reporting/modules.html). ## Installation details -Before installing this module, note that the **Magento_WishlistAnalytics** is dependent on the following modules: +Before installing this module, note that the Magento_WishlistAnalytics is dependent on the following modules: - Magento_Analytics - Magento_Wishlist -For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +For information about enabling or disabling a module, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). From 13f32b63cb06459f11718d734c96fc5541548e4e Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:04:49 +0530 Subject: [PATCH 167/242] Update README.md --- app/code/Magento/WishlistGraphQl/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/WishlistGraphQl/README.md b/app/code/Magento/WishlistGraphQl/README.md index 7f2ba3dfa44b4..c635417f3a6ec 100644 --- a/app/code/Magento/WishlistGraphQl/README.md +++ b/app/code/Magento/WishlistGraphQl/README.md @@ -1,12 +1,12 @@ # Magento_WishlistGraphQl module -The **Magento_WishlistGraphQl** module adds, removes, and updates products on the wishlist. +The Magento_WishlistGraphQl module adds, removes, and updates products on the wishlist. -The **Magento_WishlistGraphQl** module extends **Magento_GraphQl** and **Magento_Wishlist** modules. This module provides type and resolver information for GraphQL API. +The Magento_WishlistGraphQl module extends Magento_GraphQl and Magento_Wishlist modules. This module provides type and resolver information for GraphQL API. ## Installation details -Before installing this module, note that the **Magento_WishlistGraphQl** is dependent on the following modules: +Before installing this module, note that the Magento_WishlistGraphQl is dependent on the following modules: - Magento_Catalog - Magento_Checkout @@ -19,7 +19,7 @@ Before installing this module, note that the **Magento_WishlistGraphQl** is depe - Magento_Sales - Magento_Store -For information about enabling or disabling a module in Magento 2, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +For information about enabling or disabling a module, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Extensibility @@ -29,7 +29,7 @@ Extension developers can interact with the Magento_WishlistGraphQl module. For m ## Additional information -For more information about the **Magento_WishlistGraphQl** [Queries](#queries) and [Mutations](#mutations) see below: +For more information about the Magento_WishlistGraphQl [Queries](#queries) and [Mutations](#mutations) see below: ### Queries {#queries} From 0b09f8ce5dc8bd5d381a8041b09770a0f44270aa Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:06:25 +0530 Subject: [PATCH 168/242] Update README.md --- app/code/Magento/WebapiAsync/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/WebapiAsync/README.md b/app/code/Magento/WebapiAsync/README.md index f24ec19b3eb3b..96f82d8b6e493 100644 --- a/app/code/Magento/WebapiAsync/README.md +++ b/app/code/Magento/WebapiAsync/README.md @@ -13,7 +13,7 @@ Before installing this module, note that the Magento_WebapiAsync is dependent on - Magento_User - Magento_Webapi -Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +For information about enabling or disabling a module, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). ## Structure From c95fee989c7e22e868d0d3a2b84f613881ffa975 Mon Sep 17 00:00:00 2001 From: chiranjeevi <52098385+chiranjeevi-cj@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:06:48 +0530 Subject: [PATCH 169/242] Update README.md --- app/code/Magento/WebapiSecurity/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/WebapiSecurity/README.md b/app/code/Magento/WebapiSecurity/README.md index 61bf8fd1cd1e3..a355112536a00 100644 --- a/app/code/Magento/WebapiSecurity/README.md +++ b/app/code/Magento/WebapiSecurity/README.md @@ -12,4 +12,4 @@ Before installing this module, note that the Magento_WebapiSecurity is dependent - `Magento_Webapi` -Refer to [how to enable or disable modules in Magento 2](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). +For information about enabling or disabling a module, see [Enable or disable modules](https://devdocs.magento.com/guides/v2.4/install-gde/install/cli/install-cli-subcommands-enable.html). From 68ae0853aa0d6c5cb55c4d1144d1a04fc2d253b1 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 11 Jan 2021 18:35:10 +0200 Subject: [PATCH 170/242] MC-40085: Create automated test for: "Try to change category design by restricted admin" --- .../Magento/Catalog/Model/Category/AuthorizationTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php index 7583eecc065a7..55b4caaaab2aa 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Category/AuthorizationTest.php @@ -64,7 +64,7 @@ protected function tearDown(): void * * @return void */ - public function testAuthorizationWit(): void + public function testAuthorizationWithoutPermissions(): void { $category = $this->createCategoryWithData(['entity_id' => 333, 'custom_use_parent_settings' => true]); $this->expectException(AuthorizationException::class); @@ -75,7 +75,7 @@ public function testAuthorizationWit(): void /** * @return void */ - public function testWithWrongCategoryId(): void + public function testAuthorizationWithWrongCategoryId(): void { $wrongCategoryId = 56464654; $category = $this->createCategoryWithData(['entity_id' => $wrongCategoryId]); From 512f4bde460d24d6613750bbd81178b8be18131d Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Wed, 6 Jan 2021 16:32:31 +0200 Subject: [PATCH 171/242] MC-23881: When category URL page param is larger than the pagination, the page will break with elastic search 2 --- .../SearchAdapter/Query/Builder.php | 6 +- .../SearchAdapter/Query/Builder.php | 4 +- .../SearchAdapter/Query/BuilderTest.php | 189 ++++++++++++++++++ .../Unit/SearchAdapter/Query/BuilderTest.php | 72 +++++-- 4 files changed, 255 insertions(+), 16 deletions(-) create mode 100644 app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/SearchAdapter/Query/BuilderTest.php diff --git a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php index ac99c91dcfac1..a310e30d0fc70 100644 --- a/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/Elasticsearch5/SearchAdapter/Query/Builder.php @@ -22,6 +22,8 @@ */ class Builder { + private const ELASTIC_INT_MAX = 2147483647; + /** * @var Config * @since 100.2.2 @@ -83,18 +85,18 @@ public function initQuery(RequestInterface $request) { $dimension = current($request->getDimensions()); $storeId = $this->scopeResolver->getScope($dimension->getValue())->getId(); - $searchQuery = [ 'index' => $this->searchIndexNameResolver->getIndexName($storeId, $request->getIndex()), 'type' => $this->clientConfig->getEntityType(), 'body' => [ - 'from' => $request->getFrom(), + 'from' => min(self::ELASTIC_INT_MAX, $request->getFrom()), 'size' => $request->getSize(), 'stored_fields' => ['_id', '_score'], 'sort' => $this->sortBuilder->getSort($request), 'query' => [], ], ]; + return $searchQuery; } diff --git a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php index 778e73e6518e8..a37290f331bc3 100644 --- a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php +++ b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder.php @@ -23,6 +23,8 @@ */ class Builder extends Elasticsearch5Builder { + private const ELASTIC_INT_MAX = 2147483647; + /** * @var Sort */ @@ -61,7 +63,7 @@ public function initQuery(RequestInterface $request) 'index' => $this->searchIndexNameResolver->getIndexName($storeId, $request->getIndex()), 'type' => $this->clientConfig->getEntityType(), 'body' => [ - 'from' => $request->getFrom(), + 'from' => min(self::ELASTIC_INT_MAX, $request->getFrom()), 'size' => $request->getSize(), 'fields' => ['_id', '_score'], 'sort' => $this->sortBuilder->getSort($request), diff --git a/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/SearchAdapter/Query/BuilderTest.php b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/SearchAdapter/Query/BuilderTest.php new file mode 100644 index 0000000000000..8d30cd0db1ec0 --- /dev/null +++ b/app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/SearchAdapter/Query/BuilderTest.php @@ -0,0 +1,189 @@ +<?php + +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Elasticsearch\Test\Unit\Elasticsearch5\SearchAdapter\Query; + +use Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Query\Builder; +use Magento\Elasticsearch\Model\Config; +use Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation as AggregationBuilder; +use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver; +use Magento\Framework\App\ScopeInterface; +use Magento\Framework\App\ScopeResolverInterface; +use Magento\Framework\Search\Request\Dimension; +use Magento\Framework\Search\RequestInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class BuilderTest extends TestCase +{ + /** + * @var Builder + */ + protected $model; + + /** + * @var Config|MockObject + */ + protected $clientConfig; + + /** + * @var SearchIndexNameResolver|MockObject + */ + protected $searchIndexNameResolver; + + /** + * @var AggregationBuilder|MockObject + */ + protected $aggregationBuilder; + + /** + * @var RequestInterface|MockObject + */ + protected $request; + + /** + * @var ScopeResolverInterface|MockObject + */ + protected $scopeResolver; + + /** + * @var ScopeInterface|MockObject + */ + protected $scopeInterface; + + /** + * Setup method + * + * @return void + */ + protected function setUp(): void + { + $this->clientConfig = $this->getMockBuilder(Config::class) + ->onlyMethods(['getEntityType']) + ->disableOriginalConstructor() + ->getMock(); + $this->searchIndexNameResolver = $this + ->getMockBuilder(SearchIndexNameResolver::class) + ->onlyMethods(['getIndexName']) + ->disableOriginalConstructor() + ->getMock(); + $this->aggregationBuilder = $this + ->getMockBuilder(\Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation::class) + ->onlyMethods(['build']) + ->disableOriginalConstructor() + ->getMock(); + $this->request = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->scopeResolver = $this->getMockForAbstractClass( + ScopeResolverInterface::class, + [], + '', + false + ); + $this->scopeInterface = $this->getMockForAbstractClass( + ScopeInterface::class, + [], + '', + false + ); + + $this->model = new Builder( + $this->clientConfig, + $this->searchIndexNameResolver, + $this->aggregationBuilder, + $this->scopeResolver, + ); + } + + /** + * Test initQuery() method + */ + public function testInitQuery() + { + $dimensionValue = 1; + $dimension = $this->getMockBuilder(Dimension::class) + ->onlyMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $this->request->expects($this->once()) + ->method('getDimensions') + ->willReturn([$dimension]); + $dimension->expects($this->once()) + ->method('getValue') + ->willReturn($dimensionValue); + $this->scopeResolver->expects($this->once()) + ->method('getScope') + ->willReturn($this->scopeInterface); + $this->scopeInterface->expects($this->once()) + ->method('getId') + ->willReturn($dimensionValue); + $this->request->expects($this->once()) + ->method('getFrom') + ->willReturn(0); + $this->request->expects($this->once()) + ->method('getSize') + ->willReturn(10); + $this->request->expects($this->once()) + ->method('getIndex') + ->willReturn('catalogsearch_fulltext'); + $this->searchIndexNameResolver->expects($this->once()) + ->method('getIndexName') + ->willReturn('indexName'); + $this->clientConfig->expects($this->once()) + ->method('getEntityType') + ->willReturn('document'); + $this->model->initQuery($this->request); + } + + /** + * Test initQuery() method with update from value + */ + public function testInitQueryLimitFrom() + { + $dimensionValue = 1; + $dimension = $this->getMockBuilder(Dimension::class) + ->onlyMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $this->request->expects($this->once()) + ->method('getDimensions') + ->willReturn([$dimension]); + $dimension->expects($this->once()) + ->method('getValue') + ->willReturn($dimensionValue); + $this->scopeResolver->expects($this->once()) + ->method('getScope') + ->willReturn($this->scopeInterface); + $this->scopeInterface->expects($this->once()) + ->method('getId') + ->willReturn($dimensionValue); + $this->request->expects($this->once()) + ->method('getFrom') + ->willReturn(PHP_INT_MAX); + $this->request->expects($this->once()) + ->method('getSize') + ->willReturn(10); + $this->request->expects($this->once()) + ->method('getIndex') + ->willReturn('catalogsearch_fulltext'); + $this->searchIndexNameResolver->expects($this->once()) + ->method('getIndexName') + ->willReturn('indexName'); + $this->clientConfig->expects($this->once()) + ->method('getEntityType') + ->willReturn('document'); + $query = $this->model->initQuery($this->request); + $this->assertLessThanOrEqual(2147483647, $query['body']['from']); + } +} diff --git a/app/code/Magento/Elasticsearch/Test/Unit/SearchAdapter/Query/BuilderTest.php b/app/code/Magento/Elasticsearch/Test/Unit/SearchAdapter/Query/BuilderTest.php index e3ce50b303595..39c0b9ad40410 100644 --- a/app/code/Magento/Elasticsearch/Test/Unit/SearchAdapter/Query/BuilderTest.php +++ b/app/code/Magento/Elasticsearch/Test/Unit/SearchAdapter/Query/BuilderTest.php @@ -10,6 +10,7 @@ use Magento\Elasticsearch\Model\Config; use Magento\Elasticsearch\SearchAdapter\Query\Builder; use Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation as AggregationBuilder; +use Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort; use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver; use Magento\Framework\App\ScopeInterface; use Magento\Framework\App\ScopeResolverInterface; @@ -66,17 +67,17 @@ class BuilderTest extends TestCase protected function setUp(): void { $this->clientConfig = $this->getMockBuilder(Config::class) - ->setMethods(['getEntityType']) + ->onlyMethods(['getEntityType']) ->disableOriginalConstructor() ->getMock(); $this->searchIndexNameResolver = $this ->getMockBuilder(SearchIndexNameResolver::class) - ->setMethods(['getIndexName']) + ->onlyMethods(['getIndexName']) ->disableOriginalConstructor() ->getMock(); $this->aggregationBuilder = $this ->getMockBuilder(\Magento\Elasticsearch\SearchAdapter\Query\Builder\Aggregation::class) - ->setMethods(['build']) + ->onlyMethods(['build']) ->disableOriginalConstructor() ->getMock(); $this->request = $this->getMockBuilder(RequestInterface::class) @@ -94,16 +95,19 @@ protected function setUp(): void '', false ); + $sortBuilder = $this->getMockForAbstractClass( + Sort::class, + [], + '', + false + ); - $objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $objectManagerHelper->getObject( - Builder::class, - [ - 'clientConfig' => $this->clientConfig, - 'searchIndexNameResolver' => $this->searchIndexNameResolver, - 'aggregationBuilder' => $this->aggregationBuilder, - 'scopeResolver' => $this->scopeResolver - ] + $this->model = new Builder( + $this->clientConfig, + $this->searchIndexNameResolver, + $this->aggregationBuilder, + $this->scopeResolver, + $sortBuilder, ); } @@ -114,7 +118,7 @@ public function testInitQuery() { $dimensionValue = 1; $dimension = $this->getMockBuilder(Dimension::class) - ->setMethods(['getValue']) + ->onlyMethods(['getValue']) ->disableOriginalConstructor() ->getMock(); @@ -148,6 +152,48 @@ public function testInitQuery() $this->model->initQuery($this->request); } + /** + * Test initQuery() method with update from value + */ + public function testInitQueryLimitFrom() + { + $dimensionValue = 1; + $dimension = $this->getMockBuilder(Dimension::class) + ->onlyMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $this->request->expects($this->once()) + ->method('getDimensions') + ->willReturn([$dimension]); + $dimension->expects($this->once()) + ->method('getValue') + ->willReturn($dimensionValue); + $this->scopeResolver->expects($this->once()) + ->method('getScope') + ->willReturn($this->scopeInterface); + $this->scopeInterface->expects($this->once()) + ->method('getId') + ->willReturn($dimensionValue); + $this->request->expects($this->once()) + ->method('getFrom') + ->willReturn(PHP_INT_MAX); + $this->request->expects($this->once()) + ->method('getSize') + ->willReturn(10); + $this->request->expects($this->once()) + ->method('getIndex') + ->willReturn('catalogsearch_fulltext'); + $this->searchIndexNameResolver->expects($this->once()) + ->method('getIndexName') + ->willReturn('indexName'); + $this->clientConfig->expects($this->once()) + ->method('getEntityType') + ->willReturn('document'); + $query = $this->model->initQuery($this->request); + $this->assertLessThanOrEqual(2147483647, $query['body']['from']); + } + /** * Test initQuery() method */ From d099df94da8f8fb3626151b71b94aed26df1987d Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Tue, 12 Jan 2021 10:47:19 +0200 Subject: [PATCH 172/242] 30667 - in progress --- ...letterSubscriptionDisabledForStoreViewAtRegistrationTest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml index e49948e9d2aa8..bc273d84aaf34 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/StorefrontNewsletterSubscriptionDisabledForStoreViewAtRegistrationTest.xml @@ -21,11 +21,9 @@ </annotations> <before> <magentoCLI command="config:set --scope=stores --scope-code=default newsletter/general/active 0" stepKey="disableSubscriptionForStore"/> - <magentoCLI command="cache:clean config" stepKey="cleanCache"/> </before> <after> <magentoCLI command="config:set --scope=stores --scope-code=default newsletter/general/active 1" stepKey="enableSubscriptionForStore"/> - <magentoCLI command="cache:clean config" stepKey="cleanCacheAgain"/> </after> <actionGroup ref="StorefrontOpenCustomerAccountCreatePageActionGroup" stepKey="openCreateAccountPage"/> <waitForPageLoad stepKey="waitForPageLoad"/> From 3174a697766a5d74831dc3633885cae1be721dd7 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Tue, 12 Jan 2021 13:22:10 +0200 Subject: [PATCH 173/242] MC-23915: Wrong currency symbol in creditmemo_grid & sales_order_view > creditmemo grid for subtotal & Shipping and Handling fee --- .../Order/Creditmemo/Grid/Collection.php | 28 ++++ .../Creditmemo/Order/Grid/Collection.php | 28 ++++ .../Listing/Column/PurchasedPriceTest.php | 140 +++--------------- .../Listing/Column/PurchasedPrice.php | 46 +----- .../Order/Creditmemo/Grid/CollectionTest.php | 46 ++++++ .../Creditmemo/Order/Grid/CollectionTest.php | 46 ++++++ .../Listing/Column/PurchasedPriceTest.php | 69 --------- 7 files changed, 168 insertions(+), 235 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php index 6960b34b1b32f..a9c966c9006f2 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php @@ -33,4 +33,32 @@ public function __construct( ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); } + + /** + * @inheritDoc + */ + protected function _translateCondition($field, $condition) + { + if ($field !== 'order_currency_code' + && !isset($this->_map['fields'][$field]) + ) { + $this->_map['fields'][$field] = 'main_table.' . $field; + } + + return parent::_translateCondition($field, $condition); + } + + /** + * @inheritDoc + */ + protected function _renderFiltersBefore() + { + $this->getSelect()->join( + ['cgf' => $this->getTable('sales_order_grid')], + 'main_table.order_id = cgf.entity_id', + [ + 'order_currency_code'=>'order_currency_code' + ] + ); + } } diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php index eab3998eebcbd..462a72d3f7a25 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php @@ -33,4 +33,32 @@ public function __construct( ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); } + + /** + * @inheritDoc + */ + protected function _translateCondition($field, $condition) + { + if ($field !== 'order_currency_code' + && !isset($this->_map['fields'][$field]) + ) { + $this->_map['fields'][$field] = 'main_table.' . $field; + } + + return parent::_translateCondition($field, $condition); + } + + /** + * @inheritDoc + */ + protected function _renderFiltersBefore() + { + $this->getSelect()->join( + ['cgf' => $this->getTable('sales_order_grid')], + 'main_table.order_id = cgf.entity_id', + [ + 'order_currency_code'=>'order_currency_code' + ] + ); + } } diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php index f0bf116974fa8..6cbfd19f49cdd 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/PurchasedPriceTest.php @@ -8,53 +8,25 @@ namespace Magento\Sales\Test\Unit\Ui\Component\Listing\Column; use Magento\Directory\Model\Currency; -use Magento\Sales\Api\Data\OrderInterface; -use Magento\Sales\Api\Data\OrderSearchResultInterface; -use Magento\Framework\Api\SearchCriteria; -use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\Processor; -use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Ui\Component\Listing\Column\Price; use Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -/** - * Test for \Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice - */ class PurchasedPriceTest extends TestCase { /** * @var Price */ - private $model; + protected $model; /** * @var Currency|MockObject */ - private $currencyMock; - - /** - * @var OrderRepositoryInterface|MockObject - */ - private $orderRepository; - - /** - * @var SearchCriteria|MockObject - */ - private $searchCriteriaMock; - - /** - * @var OrderSearchResultInterface|MockObject - */ - private $orderSearchResultMock; - - /** - * @var OrderInterface|MockObject - */ - private $order; + protected $currencyMock; protected function setUp(): void { @@ -69,65 +41,31 @@ protected function setUp(): void ->setMethods(['load', 'format']) ->disableOriginalConstructor() ->getMock(); - $this->orderRepository = $this->getMockForAbstractClass(OrderRepositoryInterface::class); - $this->order = $this->getMockForAbstractClass(OrderInterface::class); - $this->orderSearchResultMock = $this->getMockForAbstractClass(OrderSearchResultInterface::class); - $this->searchCriteriaMock = $this->createMock(SearchCriteria::class); - $searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class); - $searchCriteriaBuilderMock->expects($this->once()) - ->method('addFilter') - ->willReturnSelf(); - - $searchCriteriaBuilderMock->expects($this->once()) - ->method('create') - ->willReturn($this->searchCriteriaMock); - $this->model = $objectManager->getObject( PurchasedPrice::class, - [ - 'currency' => $this->currencyMock, - 'context' => $contextMock, - 'orderRepository' => $this->orderRepository, - 'order' => $this->order, - 'searchCriteriaBuilder' => $searchCriteriaBuilderMock, - 'searchCriteria' => $this->searchCriteriaMock, - 'orderSearchResult' => $this->orderSearchResultMock, - ] + ['currency' => $this->currencyMock, 'context' => $contextMock] ); } - /** - * @param array $orderData - * @param array $dataSource - * @dataProvider prepareDataSourceDataProvider - */ - public function testPrepareDataSource(array $orderData,array $dataSource): void + public function testPrepareDataSource() { + $itemName = 'itemName'; $oldItemValue = 'oldItemValue'; $newItemValue = 'newItemValue'; - - $this->orderRepository->expects($this->once()) - ->method('getList') - ->with($this->searchCriteriaMock) - ->willReturn($this->orderSearchResultMock); - - $this->orderSearchResultMock->expects($this->once()) - ->method('getItems') - ->willReturn([$this->order]); - - $this->order->expects($this->once()) - ->method('getEntityId') - ->willReturn($orderData['entity_id']); - - $this->order->expects($this->once()) - ->method('getOrderCurrencyCode') - ->willReturn($orderData['order_currency_code']); - - $currencyCode = $dataSource['data']['items'][0]['order_currency_code'] ?? $orderData['order_currency_code']; + $dataSource = [ + 'data' => [ + 'items' => [ + [ + $itemName => $oldItemValue, + 'order_currency_code' => 'US' + ] + ] + ] + ]; $this->currencyMock->expects($this->once()) ->method('load') - ->with($currencyCode) + ->with($dataSource['data']['items'][0]['order_currency_code']) ->willReturnSelf(); $this->currencyMock->expects($this->once()) @@ -135,50 +73,8 @@ public function testPrepareDataSource(array $orderData,array $dataSource): void ->with($oldItemValue, [], false) ->willReturn($newItemValue); - $this->model->setData('name', 'item_name'); + $this->model->setData('name', $itemName); $dataSource = $this->model->prepareDataSource($dataSource); - $this->assertEquals($newItemValue, $dataSource['data']['items'][0]['item_name']); - } - - /** - * @return array - */ - public function prepareDataSourceDataProvider(): array - { - return [ - [ - 'orderData' => [ - 'entity_id' => 1, - 'order_currency_code' => 'US', - ], - 'dataSource' => [ - 'data' => [ - 'items' => [ - [ - 'item_name' => 'oldItemValue', - 'order_currency_code' => 'US', - 'order_id' => 1, - ] - ] - ] - ] - ], - [ - 'orderData' => [ - 'entity_id' => 1, - 'order_currency_code' => 'FR', - ], - 'dataSource' => [ - 'data' => [ - 'items' => [ - [ - 'item_name' => 'oldItemValue', - 'order_id' => 1, - ] - ] - ] - ] - ] - ]; + $this->assertEquals($newItemValue, $dataSource['data']['items'][0][$itemName]); } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php index 09e78753634c3..966673e5e7f61 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/PurchasedPrice.php @@ -7,10 +7,8 @@ namespace Magento\Sales\Ui\Component\Listing\Column; -use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\Pricing\PriceCurrencyInterface; use Magento\Directory\Model\Currency; @@ -30,16 +28,6 @@ class PurchasedPrice extends Column */ private $currency; - /** - * @var OrderRepositoryInterface - */ - private $orderRepository; - - /** - * @var SearchCriteriaBuilder - */ - private $searchCriteriaBuilder; - /** * Constructor * @@ -49,8 +37,6 @@ class PurchasedPrice extends Column * @param array $components * @param array $data * @param Currency $currency - * @param OrderRepositoryInterface $orderRepository - * @param SearchCriteriaBuilder $searchCriteriaBuilder */ public function __construct( ContextInterface $context, @@ -58,21 +44,14 @@ public function __construct( PriceCurrencyInterface $priceFormatter, array $components = [], array $data = [], - Currency $currency = null, - OrderRepositoryInterface $orderRepository = null, - SearchCriteriaBuilder $searchCriteriaBuilder = null + Currency $currency = null ) { $this->priceFormatter = $priceFormatter; $this->currency = $currency ?: \Magento\Framework\App\ObjectManager::getInstance() ->create(Currency::class); - $this->orderRepository = $orderRepository ?: \Magento\Framework\App\ObjectManager::getInstance() - ->create(OrderRepositoryInterface::class); - $this->searchCriteriaBuilder = $searchCriteriaBuilder ?: \Magento\Framework\App\ObjectManager::getInstance() - ->create(SearchCriteriaBuilder::class); parent::__construct($context, $uiComponentFactory, $components, $data); } - /** * Prepare Data Source * @@ -82,10 +61,8 @@ public function __construct( public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { - $orderIds = array_column($dataSource['data']['items'],'order_id'); - $orderCurrencyCodes = $this->getOrdersCurrency($orderIds); foreach ($dataSource['data']['items'] as & $item) { - $currencyCode = $item['order_currency_code'] ?? $orderCurrencyCodes[$item['order_id']]; + $currencyCode = isset($item['order_currency_code']) ? $item['order_currency_code'] : null; $purchaseCurrency = $this->currency->load($currencyCode); $item[$this->getData('name')] = $purchaseCurrency ->format($item[$this->getData('name')], [], false); @@ -94,23 +71,4 @@ public function prepareDataSource(array $dataSource) return $dataSource; } - - /** - * @param array $orderIds - * @return array - */ - private function getOrdersCurrency(array $orderIds): array - { - $orderCurrencyCodes = []; - - $searchCriteria = $this->searchCriteriaBuilder - ->addFilter('entity_id', $orderIds ,'in') - ->create(); - - foreach ($this->orderRepository->getList($searchCriteria)->getItems() as $order) { - $orderCurrencyCodes[$order->getEntityId()] = $order->getOrderCurrencyCode(); - } - - return $orderCurrencyCodes; - } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php new file mode 100644 index 0000000000000..4a96a381309db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid; + +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Test Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid + */ +class CollectionTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoDataFixture Magento/Sales/_files/creditmemo_list.php + * + * @return void + */ + public function testCollectionOrderCurrencyCodeExist(): void + { + /** @var $collection Collection */ + $collection = $this->objectManager->get(Collection::class); + $collection->addFieldToFilter('increment_id', ['eq' => '456']); + foreach ($collection as $item) { + $this->assertNotNull($item->getOrderCurrencyCode()); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php new file mode 100644 index 0000000000000..0b7908a122293 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid; + +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Test Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid\Order\Grid + */ +class CollectionTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoDataFixture Magento/Sales/_files/creditmemo_list.php + * + * @return void + */ + public function testCollectionOrderCurrencyCodeExist(): void + { + /** @var $collection Collection */ + $collection = $this->objectManager->get(Collection::class); + $collection->addFieldToFilter('increment_id', ['eq' => '456']); + foreach ($collection as $item) { + $this->assertNotNull($item->getOrderCurrencyCode()); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php b/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php deleted file mode 100644 index 621fd048bca94..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Sales/Ui/Component/Listing/Column/PurchasedPriceTest.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Sales\Ui\Component\Listing\Column; - -use Magento\Framework\ObjectManagerInterface; -use Magento\Sales\Model\Order; -use PHPUnit\Framework\TestCase; -use Magento\TestFramework\Helper\Bootstrap; - -/** - * Test for \Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice - * - * @magentoAppArea adminhtml - */ -class PurchasedPriceTest extends TestCase -{ - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @var PurchasedPrice - */ - private $model; - - /** - * @inheritDoc - */ - protected function setUp(): void - { - $this->objectManager = Bootstrap::getObjectManager(); - $this->model = $this->objectManager->create(PurchasedPrice::class, [ - 'data' => [ - 'name' => 'subtotal', - ], - ]); - } - - /** - * Verify prepare data source without order currency code - * - * @magentoDataFixture Magento/Sales/_files/order.php - * @return void - */ - public function testPrepareDataSourceWithoutOrderCurrencyCode(): void - { - $order = $this->objectManager->get(Order::class)->loadByIncrementId('100000001'); - - $dataSource = [ - 'data' => [ - 'items' => [ - [ - 'order_id' => $order->getEntityId(), - 'subtotal' => 100, - ], - ], - ], - ]; - - $result = $this->model->prepareDataSource($dataSource); - $this->assertEquals('$100.00', $result['data']['items'][0]['subtotal']); - } -} From d0039a3723e391d694d8a8199e85626f88ee2786 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 12 Jan 2021 14:16:44 +0200 Subject: [PATCH 174/242] MC-39621: Create automated test for: "Check products pagination on category page" --- .../Catalog/Controller/CategoryTest.php | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php index 3f023a75d0f92..00c3133c25439 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/CategoryTest.php @@ -9,12 +9,15 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Model\Category; -use Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager; -use Magento\TestFramework\Helper\Bootstrap; +use Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager; +use Magento\Catalog\Model\Product\ProductList\Toolbar as ToolbarModel; use Magento\Catalog\Model\Session; +use Magento\Framework\App\Http\Context; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Registry; use Magento\Framework\View\LayoutInterface; +use Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\AbstractController; /** @@ -45,6 +48,11 @@ class CategoryTest extends AbstractController */ private $layout; + /** + * @var Context + */ + private $httpContext; + /** * @inheritdoc */ @@ -54,14 +62,12 @@ protected function setUp(): void $this->objectManager = Bootstrap::getObjectManager(); $this->objectManager->configure([ - 'preferences' => [ - \Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager::class - => \Magento\TestFramework\Catalog\Model\CategoryLayoutUpdateManager::class - ] + 'preferences' => [LayoutUpdateManager::class => CategoryLayoutUpdateManager::class] ]); $this->registry = $this->objectManager->get(Registry::class); $this->layout = $this->objectManager->get(LayoutInterface::class); $this->session = $this->objectManager->get(Session::class); + $this->httpContext = $this->objectManager->get(Context::class); } /** @@ -205,4 +211,26 @@ public function testViewWithCustomUpdate(): void ->getHandles(); $this->assertContains("catalog_category_view_selectable_{$categoryId}_{$file}", $handles); } + + /** + * Checks that pagination value can be changed to a new one if remember pagination enabled and already have saved + * some value + * + * @magentoDataFixture Magento/Catalog/_files/category.php + * @magentoConfigFixture default/catalog/frontend/remember_pagination 1 + * + * @return void + */ + public function testViewWithRememberPaginationAndPreviousValue(): void + { + $this->session->setData(ToolbarModel::LIMIT_PARAM_NAME, 16); + $newPaginationValue = 24; + $this->getRequest()->setParams([ToolbarModel::LIMIT_PARAM_NAME => $newPaginationValue]); + $this->dispatch("catalog/category/view/id/333"); + $block = $this->layout->getBlock('product_list_toolbar'); + $this->assertNotFalse($block); + $this->assertEquals($newPaginationValue, $block->getLimit()); + $this->assertEquals($newPaginationValue, $this->session->getData(ToolbarModel::LIMIT_PARAM_NAME)); + $this->assertEquals($newPaginationValue, $this->httpContext->getValue(ToolbarModel::LIMIT_PARAM_NAME)); + } } From 5e8ca635adace0d4dbfa4b4e96a154e29868f378 Mon Sep 17 00:00:00 2001 From: Viktor Kopin <viktor.kopin@transoftgroup.com> Date: Mon, 11 Jan 2021 16:50:18 +0200 Subject: [PATCH 175/242] =?UTF-8?q?MC-37689:=20Incorrect=20displaying=20of?= =?UTF-8?q?=20a=20Product=20price=20in=20the=20=E2=80=9CShopping=20Cart?= =?UTF-8?q?=E2=80=9D=20section=20of=20the=20Admin=20panel=20in=20the=20cas?= =?UTF-8?q?e=20of=20multiple=20currencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Adminhtml/Order/Create/Sidebar/Cart.php | 5 +-- .../Order/Create/Sidebar/CartTest.php | 30 ++++++++++++++-- ...products_and_customer_and_custom_price.php | 36 +++++++++++++++++++ ...and_customer_and_custom_price_rollback.php | 12 +++++++ ...ith_two_products_and_customer_rollback.php | 13 +++++++ 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_rollback.php diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/Cart.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/Cart.php index 77765b242001f..98fd4d9bae994 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/Cart.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/Cart.php @@ -71,9 +71,10 @@ public function getItemCollection() public function getItemPrice(Product $product) { $customPrice = $this->getCartItemCustomPrice($product); - $price = $customPrice ?? $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue(); - return $this->convertPrice($price); + return $customPrice !== null + ? $this->convertPrice($customPrice) + : $this->priceCurrency->format($product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue()); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/CartTest.php b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/CartTest.php index 291fda6e2494f..13caf308259a1 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/CartTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Block/Adminhtml/Order/Create/Sidebar/CartTest.php @@ -8,9 +8,11 @@ namespace Magento\Sales\Block\Adminhtml\Order\Create\Sidebar; use Magento\Backend\Model\Session\Quote; -use Magento\Framework\ObjectManagerInterface; +use Magento\Catalog\Model\ProductRepository; use Magento\Framework\View\LayoutInterface; +use Magento\Quote\Model\QuoteRepository; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use PHPUnit\Framework\TestCase; /** @@ -23,7 +25,7 @@ */ class CartTest extends TestCase { - /** @var ObjectManagerInterface */ + /** @var ObjectManager */ private $objectManager; /** @var Cart */ @@ -32,6 +34,9 @@ class CartTest extends TestCase /** @var Quote */ private $session; + /** @var ProductRepository */ + private $productRepository; + /** * @inheritdoc */ @@ -42,6 +47,7 @@ protected function setUp(): void $this->objectManager = Bootstrap::getObjectManager(); $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Cart::class); $this->session = $this->objectManager->get(Quote::class); + $this->productRepository = $this->objectManager->get(ProductRepository::class); } /** @@ -50,7 +56,8 @@ protected function setUp(): void protected function tearDown(): void { $this->session->clearStorage(); - + $this->objectManager->removeSharedInstance(\Magento\Sales\Model\AdminOrder\Create::class, true); + $this->objectManager->removeSharedInstance(QuoteRepository::class); parent::tearDown(); } @@ -77,4 +84,21 @@ public function testClearShoppingCartButton(): void $this->assertEquals(sprintf("order.clearShoppingCart('%s')", $confirmation), $button->getOnclick()); $this->assertEquals(__('Clear Shopping Cart'), $button->getLabel()); } + + /** + * @magentoDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoDataFixture Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price.php + * + * @magentoConfigFixture default/currency/options/base USD + * @magentoConfigFixture current_store currency/options/default CNY + * @magentoConfigFixture current_store currency/options/allow CNY,USD + */ + public function testGetItemPriceConvert() + { + $this->session->setCustomerId(1); + $customPrice = $this->block->getItemPrice($this->productRepository->get('simple')); + $this->assertStringContainsString('84.00', $customPrice); + $price = $this->block->getItemPrice($this->productRepository->get('custom-design-simple-product')); + $this->assertStringContainsString('70.00', $price); + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price.php new file mode 100644 index 0000000000000..456dbd6b86abd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Model\ProductRepository; +use Magento\Quote\Model\Quote\Item\Updater; +use Magento\Quote\Model\QuoteFactory; +use Magento\Quote\Model\ResourceModel\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Sales/_files/quote_with_two_products_and_customer.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = $objectManager->get(QuoteFactory::class); +/** @var Quote $quoteResource */ +$quoteResource = $objectManager->get(Quote::class); +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test01', 'reserved_order_id'); +$productRepository = $objectManager->get(ProductRepository::class); +$quoteItem = $quote->getItemByProduct($productRepository->get('simple')); +/** @var Updater $updater */ +$updater = $objectManager->get(Updater::class); +$updater->update( + $quoteItem, + [ + 'qty' => 1, + 'custom_price' => 12, + ] +); +$quote->collectTotals(); +$quoteResource->save($quote); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price_rollback.php new file mode 100644 index 0000000000000..6405d3b9b959a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_and_custom_price_rollback.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture( + 'Magento/Sales/_files/quote_with_two_products_and_customer_rollback.php' +); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_rollback.php new file mode 100644 index 0000000000000..6a66c6515cf44 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_two_products_and_customer_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\Catalog\Api\ProductRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Checkout/_files/quote_with_address_rollback.php'); From 17330fff39e423b4443bb6a1299c08cead23511a Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Tue, 12 Jan 2021 14:32:48 +0200 Subject: [PATCH 176/242] MC-39704: Create automated test for: "Register simple product instead of Configurable" --- .../Magento/Swatches/Helper/DataTest.php | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php new file mode 100644 index 0000000000000..1ae707fce8400 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Swatches\Helper; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for helper swatch attributes for product. + * + * @see \Magento\Swatches\Helper\Data + * @magentoDbIsolation enabled + */ +class DataTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var Data */ + private $helper; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->helper = $this->objectManager->get(Data::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * @return void + */ + public function testGetSwatchAttributesAsArray(): void + { + $product = $this->productRepository->get('simple2'); + $result = $this->helper->getSwatchAttributesAsArray($product); + $this->assertEquals([], $result); + } +} From 02a93cbd776e7a30a796ac4397ba050e047ebcf4 Mon Sep 17 00:00:00 2001 From: rostyslav-hymon <rostyslav.hymon@transoftgroup.com> Date: Tue, 12 Jan 2021 14:57:06 +0200 Subject: [PATCH 177/242] MC-40305: Can not delete upsell and crosssell products via import --- .../Model/Import/Product/LinkProcessor.php | 2 +- .../Model/Import/ProductTest.php | 41 ++++++++++++++++--- ...ort_with_product_links_with_empty_data.csv | 2 + ...product_export_with_product_links_data.php | 29 +++++++++---- 4 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_product_links_with_empty_data.csv diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/LinkProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/LinkProcessor.php index 22a83671f630a..84cdc4608148c 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/LinkProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/LinkProcessor.php @@ -220,7 +220,7 @@ private function deleteProductsLinks( if (!empty($linksToDelete) && Import::BEHAVIOR_APPEND === $importEntity->getBehavior()) { foreach ($linksToDelete as $linkTypeId => $productIds) { if (!empty($productIds)) { - $whereLinkId = $importEntity->getConnection()->quoteInto('link_type_id', $linkTypeId); + $whereLinkId = $importEntity->getConnection()->quoteInto('link_type_id = ?', $linkTypeId); $whereProductId = $importEntity->getConnection()->quoteInto( 'product_id IN (?)', array_unique($productIds) 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 53e32483ee3d6..ceb07e3445c0e 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1721,15 +1721,23 @@ public function testValidateUrlKeysMultipleStores() } /** + * Test import product with product links and empty value + * + * @param string $pathToFile + * @param bool $expectedResultCrossell + * @param bool $expectedResultUpsell + * * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_product_links_data.php * @magentoAppArea adminhtml * @magentoDbIsolation enabled * @magentoAppIsolation enabled + * @dataProvider getEmptyLinkedData */ - public function testProductLinksWithEmptyValue() - { - // import data from CSV file - $pathToFile = __DIR__ . '/_files/products_to_import_with_product_links_with_empty_value.csv'; + public function testProductLinksWithEmptyValue( + string $pathToFile, + bool $expectedResultCrossell, + bool $expectedResultUpsell + ): void { $filesystem = BootstrapHelper::getObjectManager()->create(Filesystem::class); $directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); @@ -1759,8 +1767,29 @@ public function testProductLinksWithEmptyValue() $product = BootstrapHelper::getObjectManager()->create(Product::class); $product->load($productId); - $this->assertEmpty($product->getCrossSellProducts()); - $this->assertEmpty($product->getUpSellProducts()); + $this->assertEquals(empty($product->getCrossSellProducts()), $expectedResultCrossell); + $this->assertEquals(empty($product->getUpSellProducts()), $expectedResultUpsell); + } + + /** + * Get data for empty linked product + * + * @return array[] + */ + public function getEmptyLinkedData(): array + { + return [ + [ + __DIR__ . '/_files/products_to_import_with_product_links_with_empty_value.csv', + true, + true, + ], + [ + __DIR__ . '/_files/products_to_import_with_product_links_with_empty_data.csv', + false, + true, + ], + ]; } /** diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_product_links_with_empty_data.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_product_links_with_empty_data.csv new file mode 100644 index 0000000000000..d8812defa0828 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_product_links_with_empty_data.csv @@ -0,0 +1,2 @@ +sku,crosssell_skus,crosssell_position,upsell_skus,upsell_position +simple,,,__EMPTY__VALUE__,__EMPTY__VALUE__ diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php index 5dde578a1341f..8ee35d747ea1a 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php @@ -18,7 +18,26 @@ $objectManager = Bootstrap::getObjectManager(); /** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->create(ProductRepositoryInterface::class); -$product = $productRepository->get('simple_ms_1'); +/** @var \Magento\Catalog\Api\Data\ProductLinkInterface $productLink */ +$productCrosssellLink = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Api\Data\ProductLinkInterface::class); +$productCrosssellLink->setSku('simple'); +$productCrosssellLink->setLinkedProductSku('simple_ms_1'); +$productCrosssellLink->setPosition(2); +$productCrosssellLink->setLinkType('crosssell'); +$productUpsellLink = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Api\Data\ProductLinkInterface::class); +$productUpsellLink->setSku('simple'); +$productUpsellLink->setLinkedProductSku('simple_ms_1'); +$productUpsellLink->setPosition(1); +$productUpsellLink->setLinkType('upsell'); +$productRelatedLink = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Api\Data\ProductLinkInterface::class); +$productRelatedLink->setSku('simple'); +$productRelatedLink->setLinkedProductSku('simple_ms_1'); +$productRelatedLink->setPosition(3); +$productRelatedLink->setLinkType('related'); + $productModel = $objectManager->create( \Magento\Catalog\Model\Product::class ); @@ -51,10 +70,6 @@ true )->setCategoryIds( [333] -)->setUpSellLinkData( - [$product->getId() => ['position' => 1]] -)->setCrossSellLinkData( - [$product->getId() => ['position' => 2]] -)->setRelatedLinkData( - [$product->getId() => ['position' => 3]] +)->setProductLinks( + [$productCrosssellLink, $productUpsellLink, $productRelatedLink] )->save(); From 4c62af0e7d8bb9cc103725c62710d86e34849064 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Tue, 12 Jan 2021 16:33:50 +0200 Subject: [PATCH 178/242] MC-30152: Bundle Product / Create / Price validation for dynamic price --- ...namicPriceOnProductEditPageActionGroup.xml | 15 +++++++ ...sappearedAfterSwitchToDynamicPriceTest.xml | 42 +++++++++++++++++++ ...PressEnterOnProductEditPageActionGroup.xml | 20 +++++++++ ...PriceFieldOnProductEditPageActionGroup.xml | 14 +++++++ ...PriceFieldOnProductEditPageActionGroup.xml | 19 +++++++++ .../base/web/js/lib/core/element/links.js | 4 ++ 6 files changed, 114 insertions(+) create mode 100644 app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup.xml create mode 100644 app/code/Magento/Bundle/Test/Mftf/Test/AdminBundleProductPriceValidationErrorDisappearedAfterSwitchToDynamicPriceTest.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup.xml diff --git a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup.xml b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup.xml new file mode 100644 index 0000000000000..d822f5d6d7a47 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup.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="AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup"> + <waitForElementVisible selector="{{AdminProductFormBundleSection.dynamicPriceToggle}}" stepKey="waitForToggleDynamicPrice"/> + <checkOption selector="{{AdminProductFormBundleSection.dynamicPriceToggle}}" stepKey="switchDynamicPriceToggle"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminBundleProductPriceValidationErrorDisappearedAfterSwitchToDynamicPriceTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminBundleProductPriceValidationErrorDisappearedAfterSwitchToDynamicPriceTest.xml new file mode 100644 index 0000000000000..4ff1121f48e62 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminBundleProductPriceValidationErrorDisappearedAfterSwitchToDynamicPriceTest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- Test XML Example --> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminBundleProductPriceValidationErrorDisappearedAfterSwitchToDynamicPriceTest"> + <annotations> + <features value="Bundle"/> + <stories value="Create/Edit bundle product in Admin"/> + <title value="Assert error message for price field"/> + <description value="Verify error message for price field is not visible when toggle Dynamic Price is disabled"/> + <severity value="MAJOR"/> + <testCaseId value="MC-40309"/> + <useCaseId value="MC-30152"/> + <group value="bundle"/> + </annotations> + + <before> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> + <after> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="AdminOpenNewProductFormPageActionGroup" stepKey="openNewBundleProductPage"> + <argument name="productType" value="bundle"/> + </actionGroup> + <actionGroup ref="AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup" stepKey="disableDynamicPrice"/> + <actionGroup ref="AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup" stepKey="fillProductPriceField"> + <argument name="price" value="test"/> + </actionGroup> + <actionGroup ref="AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup" stepKey="assertVisibleError"> + <argument name="errorMessage" value="Please enter a number 0 or greater in this field."/> + </actionGroup> + <actionGroup ref="AdminToggleSwitchDynamicPriceOnProductEditPageActionGroup" stepKey="enableDynamicPrice"/> + <actionGroup ref="AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup" stepKey="assertNotVisibleError"/> + </test> +</tests> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup.xml new file mode 100644 index 0000000000000..ed10792d09cfd --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup.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="AdminFillProductPriceFieldAndPressEnterOnProductEditPageActionGroup"> + <arguments> + <argument name="price" type="string"/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormSection.productPrice}}" stepKey="waitForPriceField"/> + <fillField selector="{{AdminProductFormSection.productPrice}}" userInput="{{price}}" stepKey="fillPriceField"/> + <pressKey selector="{{AdminProductFormSection.productPrice}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::ENTER]" stepKey="pressEnterButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup.xml new file mode 100644 index 0000000000000..c1281fdaa4999 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup.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="AssertAdminNoValidationErrorForPriceFieldOnProductEditPageActionGroup"> + <dontSeeElement selector="{{AdminProductFormSection.priceFieldError}}" stepKey="dontSeeValidationError"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup.xml new file mode 100644 index 0000000000000..c206ee582b519 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup.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="AssertAdminValidationErrorAppearedForPriceFieldOnProductEditPageActionGroup"> + <arguments> + <argument name="errorMessage" type="string" defaultValue="This is a required field."/> + </arguments> + + <waitForElementVisible selector="{{AdminProductFormSection.priceFieldError}}" stepKey="waitForValidationError"/> + <see selector="{{AdminProductFormSection.priceFieldError}}" userInput="{{errorMessage}}" stepKey="seeElementValidationError"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js b/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js index 27dd8e2ffb59c..427e142036ae3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/element/links.js @@ -79,6 +79,10 @@ define([ component.set(property, value, owner); + if (property === 'disabled' && value) { + component.set('validate', value, owner); + } + if (linked) { linked.mute = false; } From 39a0888da6fef00a62edc9375a4b872445642d44 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Tue, 12 Jan 2021 17:28:40 +0200 Subject: [PATCH 179/242] MC-39704: Create automated test for: "Register simple product instead of Configurable" --- .../testsuite/Magento/Swatches/Helper/DataTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php index 1ae707fce8400..2e9ea5aba536c 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Helper/DataTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\TestCase; /** - * Tests for helper swatch attributes for product. + * Tests for product swatch attribute helper. * * @see \Magento\Swatches\Helper\Data * @magentoDbIsolation enabled @@ -39,6 +39,7 @@ protected function setUp(): void $this->objectManager = Bootstrap::getObjectManager(); $this->helper = $this->objectManager->get(Data::class); $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); } /** @@ -48,7 +49,6 @@ protected function setUp(): void public function testGetSwatchAttributesAsArray(): void { $product = $this->productRepository->get('simple2'); - $result = $this->helper->getSwatchAttributesAsArray($product); - $this->assertEquals([], $result); + $this->assertEmpty($this->helper->getSwatchAttributesAsArray($product)); } } From cb793f8ac24ebabbafb104b52e8acbf8ddccd20e Mon Sep 17 00:00:00 2001 From: Vadim Malesh <51680850+engcom-Charlie@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:40:00 +0200 Subject: [PATCH 180/242] change the comment to prevent BIC Co-authored-by: Gabriel da Gama <gabriel@gabrielgama.com.br> --- .../Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 18f5b91348191..36b1edc304306 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -187,7 +187,7 @@ <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{CustomerAddressSimple.telephone}}" stepKey="fillPhone" /> <!-- Click next button to open payment section --> - <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNextBtn"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Check order summary in checkout --> From cbc6beaa982e9430765365d35701a956c3bb363f Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Tue, 12 Jan 2021 17:41:30 +0200 Subject: [PATCH 181/242] Refactoring for BC --- .../Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml index 18f5b91348191..36b1edc304306 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/OnePageCheckoutWithAllProductTypesTest.xml @@ -187,7 +187,7 @@ <fillField selector="{{CheckoutShippingGuestInfoSection.telephone}}" userInput="{{CustomerAddressSimple.telephone}}" stepKey="fillPhone" /> <!-- Click next button to open payment section --> - <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNext"/> + <actionGroup ref="StorefrontGuestCheckoutProceedToPaymentStepActionGroup" stepKey="clickNextBtn"/> <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="waitForShipmentPageLoad"/> <!-- Check order summary in checkout --> From 8417b88627435438e67174a4f14122edff9417b2 Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Tue, 12 Jan 2021 18:23:34 +0200 Subject: [PATCH 182/242] MC-23915: Wrong currency symbol in creditmemo_grid & sales_order_view > creditmemo grid for subtotal & Shipping and Handling fee --- .../Model/ResourceModel/Order/Creditmemo/Grid/Collection.php | 4 ++-- .../ResourceModel/Order/Creditmemo/Order/Grid/Collection.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php index a9c966c9006f2..46e26c97556e6 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php @@ -53,11 +53,11 @@ protected function _translateCondition($field, $condition) */ protected function _renderFiltersBefore() { - $this->getSelect()->join( + $this->getSelect()->joinLeft( ['cgf' => $this->getTable('sales_order_grid')], 'main_table.order_id = cgf.entity_id', [ - 'order_currency_code'=>'order_currency_code' + 'order_currency_code' => 'order_currency_code', ] ); } diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php index 462a72d3f7a25..4d446b6c7620d 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php @@ -53,11 +53,11 @@ protected function _translateCondition($field, $condition) */ protected function _renderFiltersBefore() { - $this->getSelect()->join( + $this->getSelect()->joinLeft( ['cgf' => $this->getTable('sales_order_grid')], 'main_table.order_id = cgf.entity_id', [ - 'order_currency_code'=>'order_currency_code' + 'order_currency_code' => 'order_currency_code', ] ); } From 0b3c5f11745795d453e66aa6b6f1bf213ab51ae8 Mon Sep 17 00:00:00 2001 From: Joan He <johe@adobe.com> Date: Tue, 12 Jan 2021 15:10:07 -0600 Subject: [PATCH 183/242] B2B-1637: Fix GET_LOCK error on read-only slave connection --- app/code/Magento/Config/etc/di.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Config/etc/di.xml b/app/code/Magento/Config/etc/di.xml index 4277ca0a6de26..76cfdbfa60b82 100644 --- a/app/code/Magento/Config/etc/di.xml +++ b/app/code/Magento/Config/etc/di.xml @@ -96,7 +96,7 @@ <virtualType name="systemConfigQueryLocker" type="Magento\Framework\Cache\LockGuardedCacheLoader"> <arguments> - <argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Database</argument> + <argument name="locker" xsi:type="object">Magento\Framework\Lock\Proxy</argument> </arguments> </virtualType> From 0bf51ecab28d3e13853932391ecc94bf8bca2c66 Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Tue, 12 Jan 2021 16:36:07 -0600 Subject: [PATCH 184/242] MCP-89: Move product batch size variable to environment --- .../Indexer/Category/Product/Action/Full.php | 26 +++++++++++- .../Indexer/Price/BatchSizeCalculator.php | 40 ++++++++++++++++--- .../Model/Indexer/Stock/Action/Full.php | 34 ++++++++++++++-- .../CatalogSearch/Model/Indexer/Fulltext.php | 24 ++++++++++- 4 files changed, 111 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php index a7c5cdf412e6e..e94c7a4ee0cfc 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php +++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php @@ -12,6 +12,8 @@ use Magento\Catalog\Model\Config; use Magento\Catalog\Model\Indexer\Category\Product\AbstractAction; use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher; +use Magento\Catalog\Model\Indexer\Category\Product; +use Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Query\Generator as QueryGenerator; @@ -63,6 +65,18 @@ class Full extends AbstractAction */ private $processManager; + /** + * @var DeploymentConfig|null + */ + private $deploymentConfig; + + /** + * Deployment config path + * + * @var string + */ + private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/'; + /** * @param ResourceConnection $resource * @param StoreManagerInterface $storeManager @@ -73,7 +87,8 @@ class Full extends AbstractAction * @param MetadataPool|null $metadataPool * @param int|null $batchRowsCount * @param ActiveTableSwitcher|null $activeTableSwitcher - * @param ProcessManager $processManager + * @param ProcessManager|null $processManager + * @param DeploymentConfig|null $deploymentConfig * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -86,7 +101,8 @@ public function __construct( MetadataPool $metadataPool = null, $batchRowsCount = null, ActiveTableSwitcher $activeTableSwitcher = null, - ProcessManager $processManager = null + ProcessManager $processManager = null, + ?DeploymentConfig $deploymentConfig = null ) { parent::__construct( $resource, @@ -107,6 +123,7 @@ public function __construct( $this->batchRowsCount = $batchRowsCount; $this->activeTableSwitcher = $activeTableSwitcher ?: $objectManager->get(ActiveTableSwitcher::class); $this->processManager = $processManager ?: $objectManager->get(ProcessManager::class); + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); } /** @@ -266,6 +283,11 @@ private function reindexCategoriesBySelect(Select $basicSelect, $whereCondition, $columns = array_keys( $this->connection->describeTable($this->tableMaintainer->getMainTmpTable((int)$store->getId())) ); + + $this->batchRowsCount = $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . Product::INDEXER_ID + ) ?? $this->batchRowsCount; + $this->batchSizeManagement->ensureBatchSize($this->connection, $this->batchRowsCount); $select = $this->connection->select(); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculator.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculator.php index 810b1b9a07c4f..85ee8360b7127 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculator.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculator.php @@ -6,6 +6,10 @@ namespace Magento\Catalog\Model\ResourceModel\Product\Indexer\Price; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; +use Magento\Catalog\Model\Indexer\Product\Price\Processor; + /** * Ensure that size of index MEMORY table is enough for configured rows count in batch. */ @@ -26,17 +30,34 @@ class BatchSizeCalculator */ private $batchSizeAdjusters; + /** + * @var DeploymentConfig|null + */ + private $deploymentConfig; + + /** + * Deployment config path + * + * @var string + */ + private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/'; + /** * BatchSizeCalculator constructor. * @param array $batchRowsCount * @param array $estimators * @param array $batchSizeAdjusters */ - public function __construct(array $batchRowsCount, array $estimators, array $batchSizeAdjusters) - { + public function __construct( + array $batchRowsCount, + array $estimators, + array $batchSizeAdjusters, + ?DeploymentConfig $deploymentConfig = null + ) { $this->batchRowsCount = $batchRowsCount; $this->estimators = $estimators; $this->batchSizeAdjusters = $batchSizeAdjusters; + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); } /** @@ -50,9 +71,18 @@ public function __construct(array $batchRowsCount, array $estimators, array $bat */ public function estimateBatchSize(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $indexerTypeId) { - $batchRowsCount = isset($this->batchRowsCount[$indexerTypeId]) - ? $this->batchRowsCount[$indexerTypeId] - : $this->batchRowsCount['default']; + $batchRowsCount = $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . Processor::INDEXER_ID . '/' . $indexerTypeId, + $batchRowsCount = $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . Processor::INDEXER_ID . '/' . 'default' + ) + ); + + if (is_null($batchRowsCount)) { + $batchRowsCount = isset($this->batchRowsCount[$indexerTypeId]) + ? $this->batchRowsCount[$indexerTypeId] + : $this->batchRowsCount['default']; + } /** @var \Magento\Framework\Indexer\BatchSizeManagementInterface $calculator */ $calculator = isset($this->estimators[$indexerTypeId]) diff --git a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Action/Full.php b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Action/Full.php index f85f3f3576279..d8bf4f858047c 100644 --- a/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Action/Full.php +++ b/app/code/Magento/CatalogInventory/Model/Indexer/Stock/Action/Full.php @@ -28,6 +28,8 @@ use Magento\Framework\Exception\LocalizedException; use Magento\CatalogInventory\Model\Indexer\Stock\AbstractAction; use Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StockInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor; /** * Class Full reindex action @@ -71,6 +73,18 @@ class Full extends AbstractAction */ private $batchQueryGenerator; + /** + * @var DeploymentConfig|null + */ + private $deploymentConfig; + + /** + * Deployment config path + * + * @var string + */ + private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/'; + /** * @param ResourceConnection $resource * @param StockFactory $indexerFactory @@ -83,6 +97,7 @@ class Full extends AbstractAction * @param array $batchRowsCount * @param ActiveTableSwitcher|null $activeTableSwitcher * @param QueryGenerator|null $batchQueryGenerator + * @param DeploymentConfig|null $deploymentConfig * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -96,7 +111,8 @@ public function __construct( BatchProviderInterface $batchProvider = null, array $batchRowsCount = [], ActiveTableSwitcher $activeTableSwitcher = null, - QueryGenerator $batchQueryGenerator = null + QueryGenerator $batchQueryGenerator = null, + ?DeploymentConfig $deploymentConfig = null ) { parent::__construct( $resource, @@ -115,6 +131,7 @@ public function __construct( $this->activeTableSwitcher = $activeTableSwitcher ?: ObjectManager::getInstance() ->get(ActiveTableSwitcher::class); $this->batchQueryGenerator = $batchQueryGenerator ?: ObjectManager::getInstance()->get(QueryGenerator::class); + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); } /** @@ -141,9 +158,18 @@ public function execute($ids = null): void $connection = $indexer->getConnection(); $tableName = $this->activeTableSwitcher->getAdditionalTableName($indexer->getMainTable()); - $batchRowCount = isset($this->batchRowsCount[$indexer->getTypeId()]) - ? $this->batchRowsCount[$indexer->getTypeId()] - : $this->batchRowsCount['default']; + $batchRowCount = $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . Processor::INDEXER_ID . '/' . $indexer->getTypeId(), + $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . Processor::INDEXER_ID . '/' . 'default' + ) + ); + + if (is_null($batchRowCount)) { + $batchRowCount = isset($this->batchRowsCount[$indexer->getTypeId()]) + ? $this->batchRowsCount[$indexer->getTypeId()] + : $this->batchRowsCount['default']; + } $this->batchSizeManagement->ensureBatchSize($connection, $batchRowCount); diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php index f72516d28c46f..849137b57b52c 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php @@ -15,6 +15,7 @@ use Magento\Framework\Indexer\SaveHandler\IndexerInterface; use Magento\Store\Model\StoreDimensionProvider; use Magento\Indexer\Model\ProcessManager; +use Magento\Framework\App\DeploymentConfig; /** * Provide functionality for Fulltext Search indexing. @@ -88,6 +89,18 @@ class Fulltext implements */ private $batchSize; + /** + * @var DeploymentConfig|null + */ + private $deploymentConfig; + + /** + * Deployment config path + * + * @var string + */ + private const DEPLOYMENT_CONFIG_INDEXER_BATCHES = 'indexer/batch_size/'; + /** * @param FullFactory $fullActionFactory * @param IndexerHandlerFactory $indexerHandlerFactory @@ -96,8 +109,9 @@ class Fulltext implements * @param StateFactory $indexScopeStateFactory * @param DimensionProviderInterface $dimensionProvider * @param array $data - * @param ProcessManager $processManager + * @param ProcessManager|null $processManager * @param int|null $batchSize + * @param DeploymentConfig $deploymentConfig * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -109,7 +123,8 @@ public function __construct( DimensionProviderInterface $dimensionProvider, array $data, ProcessManager $processManager = null, - ?int $batchSize = null + ?int $batchSize = null, + ?DeploymentConfig $deploymentConfig = null ) { $this->fullAction = $fullActionFactory->create(['data' => $data]); $this->indexerHandlerFactory = $indexerHandlerFactory; @@ -120,6 +135,7 @@ public function __construct( $this->dimensionProvider = $dimensionProvider; $this->processManager = $processManager ?: ObjectManager::getInstance()->get(ProcessManager::class); $this->batchSize = $batchSize ?? self::BATCH_SIZE; + $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); } /** @@ -165,6 +181,10 @@ public function executeByDimensions(array $dimensions, \Traversable $entityIds = $currentBatch = []; $i = 0; + $this->batchSize = $this->deploymentConfig->get( + self::DEPLOYMENT_CONFIG_INDEXER_BATCHES . self::INDEXER_ID + ) ?? $this->batchSize; + foreach ($entityIds as $entityId) { $currentBatch[] = $entityId; if (++$i === $this->batchSize) { From 195b7551de937ba347345ea18524e3b9550a9cc1 Mon Sep 17 00:00:00 2001 From: Arnob Saha <arnobsh@gmail.com> Date: Tue, 5 Jan 2021 16:53:22 -0600 Subject: [PATCH 185/242] MC-40296: MFTF test failing randomly AdminValidateLastReviewDateForReviewsByProductsReportTest - Skipping the risky test for random failure --- ...minValidateLastReviewDateForReviewsByProductsReportTest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml b/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml index 3405314f24f78..8b75a0f608548 100644 --- a/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml +++ b/app/code/Magento/Review/Test/Mftf/Test/AdminValidateLastReviewDateForReviewsByProductsReportTest.xml @@ -17,6 +17,9 @@ <severity value="MAJOR"/> <useCaseId value="MC-39737"/> <testCaseId value="MC-39838"/> + <skip> + <issueId value="MQE-2288" /> + </skip> </annotations> <before> <!--Step1. Login as admin--> From 9ef6460c43a70e43bda79d8967b325ad6af3dcda Mon Sep 17 00:00:00 2001 From: engcom-Kilo <mikola.malevanec@transoftgroup.com> Date: Tue, 12 Jan 2021 16:00:19 +0200 Subject: [PATCH 186/242] MC-40344: Sorting by position on product search via REST API does not work. --- .../Catalog/Model/ProductRepository.php | 36 +++- .../Test/Unit/Model/ProductRepositoryTest.php | 3 + .../Api/ProductRepositoryInterfaceTest.php | 165 +++++++++++++----- .../Catalog/_files/products_for_search.php | 27 ++- 4 files changed, 176 insertions(+), 55 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index fefeafe46e1c4..09b3f8aae2330 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -17,6 +17,7 @@ use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; +use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\DB\Adapter\ConnectionException; use Magento\Framework\DB\Adapter\DeadlockException; use Magento\Framework\DB\Adapter\LockWaitException; @@ -619,7 +620,7 @@ public function deleteById($sku) /** * @inheritdoc */ - public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) + public function getList(SearchCriteriaInterface $searchCriteria) { /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */ $collection = $this->collectionFactory->create(); @@ -628,6 +629,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr $collection->addAttributeToSelect('*'); $collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner'); $collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner'); + $this->joinPositionField($collection, $searchCriteria); $this->collectionProcessor->process($searchCriteria, $collection); @@ -856,4 +858,36 @@ private function saveProduct($product): void ); } } + + /** + * Join category position field to make sorting by position possible. + * + * @param Collection $collection + * @param SearchCriteriaInterface $searchCriteria + * @return void + */ + private function joinPositionField( + Collection $collection, + SearchCriteriaInterface $searchCriteria + ): void { + $categoryIds = [[]]; + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + if ($filter->getField() === 'category_id') { + $categoryIds[] = explode(',', $filter->getValue()); + } + } + } + $categoryIds = array_unique(array_merge(...$categoryIds)); + if (count($categoryIds) === 1) { + $collection->joinField( + 'position', + 'catalog_category_product', + 'position', + 'product_id=entity_id', + ['category_id' => current($categoryIds)], + 'left' + ); + } + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index 129873a067d97..c456ebeb101f4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -852,6 +852,9 @@ public function testDeleteById() public function testGetList() { $searchCriteriaMock = $this->getMockForAbstractClass(SearchCriteriaInterface::class); + $searchCriteriaMock->expects($this->once()) + ->method('getFilterGroups') + ->willReturn([]); $collectionMock = $this->createMock(Collection::class); $this->collectionFactory->expects($this->once())->method('create')->willReturn($collectionMock); $this->product->method('getSku')->willReturn('simple'); 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 d77737edadafa..0f12a7aad9cfc 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -1,4 +1,5 @@ <?php + /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. @@ -23,6 +24,7 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Webapi\Exception as HTTPExceptionCodes; +use Magento\Framework\Webapi\Rest\Request; use Magento\Integration\Api\AdminTokenServiceInterface; use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Api\StoreWebsiteRelationInterface; @@ -64,7 +66,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract ProductInterface::SKU => 'simple_with_cross', ProductInterface::NAME => 'Simple Product With Related Product', ProductInterface::TYPE_ID => 'simple', - ProductInterface::PRICE => 10 + ProductInterface::PRICE => 10, ], ]; @@ -143,7 +145,7 @@ protected function getProduct($sku, $storeCode = null) $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -165,7 +167,7 @@ public function testGetNoSuchEntityException() $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $invalidSku, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -245,7 +247,7 @@ public function testUpdateWithDeleteWebsites() $websitesData = [ 'website_ids' => [ $website->getId(), - ] + ], ]; $productBuilder[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = $websitesData; $response = $this->updateProduct($productBuilder); @@ -345,7 +347,7 @@ public function testCreateWithMultipleWebsites() 'website_ids' => [ 1, (int)$website->getId(), - ] + ], ]; $productBuilder[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = $websitesData; $response = $this->saveProduct($productBuilder); @@ -372,7 +374,7 @@ public function testCreateWithNonDefaultStoreWebsite() $websitesData = [ 'website_ids' => [ $website->getId(), - ] + ], ]; $productBuilder[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = $websitesData; $response = $this->saveProduct($productBuilder); @@ -400,7 +402,7 @@ public function testUpdateWithNonDefaultStoreWebsite() $websitesData = [ 'website_ids' => [ $website->getId(), - ] + ], ]; $productBuilder[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = $websitesData; $response = $this->updateProduct($productBuilder); @@ -557,8 +559,8 @@ public function testProductLinks() ProductInterface::STATUS => 1, ProductInterface::ATTRIBUTE_SET_ID => 4, ProductInterface::EXTENSION_ATTRIBUTES_KEY => [ - 'stock_item' => $this->getStockItemData() - ] + 'stock_item' => $this->getStockItemData(), + ], ]; $this->saveProduct($productData); @@ -568,7 +570,7 @@ public function testProductLinks() "link_type" => "related", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", - "position" => 0 + "position" => 0, ]; $productWithRelatedData = [ ProductInterface::SKU => "product_simple_with_related_500", @@ -578,7 +580,7 @@ public function testProductLinks() ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, ProductInterface::ATTRIBUTE_SET_ID => 4, - "product_links" => [$productLinkData] + "product_links" => [$productLinkData], ]; $this->saveProduct($productWithRelatedData); @@ -595,7 +597,7 @@ public function testProductLinks() "link_type" => "upsell", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", - "position" => 0 + "position" => 0, ]; $productWithUpsellData = [ ProductInterface::SKU => "product_simple_with_related_500", @@ -605,7 +607,7 @@ public function testProductLinks() ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, ProductInterface::ATTRIBUTE_SET_ID => 4, - "product_links" => [$productLinkData] + "product_links" => [$productLinkData], ]; $this->saveProduct($productWithUpsellData); @@ -625,7 +627,7 @@ public function testProductLinks() ProductInterface::PRICE => 100, ProductInterface::STATUS => 1, ProductInterface::ATTRIBUTE_SET_ID => 4, - "product_links" => [] + "product_links" => [], ]; $this->saveProduct($productWithNoLinkData); @@ -809,7 +811,7 @@ public function testProductWithMediaGallery() 'disabled' => false, 'types' => [], 'file' => '/t/i/' . $filename1, - ] + ], ]; $this->assertEquals($expectedValue, $mediaGalleryEntries); //don't set the media_gallery_entries field, existing entry should not be touched @@ -895,7 +897,7 @@ protected function updateProduct($product, ?string $token = null) $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + 'httpMethod' => Request::HTTP_METHOD_PUT, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -950,7 +952,7 @@ public function testGetList() $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($searchCriteria), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1006,8 +1008,8 @@ public function testGetListWithAdditionalParams() 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($searchCriteria) . '&fields=' . $additionalParams, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, - ] + 'httpMethod' => Request::HTTP_METHOD_GET, + ], ]; $response = $this->_webApiCall($serviceInfo, $searchCriteria); @@ -1056,7 +1058,7 @@ public function testGetListWithFilteringByWebsite() $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($searchCriteria), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1089,7 +1091,7 @@ public function testGetListWithFilteringByStore(array $searchCriteria, array $sk $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($searchCriteria), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1155,8 +1157,8 @@ public function testGetListWithFilteringByStoreDataProvider() ], ], ['simple-2', 'simple-1'], - null - ] + null, + ], ]; } @@ -1194,7 +1196,7 @@ public function testGetListPagination(int $pageSize, int $currentPage, int $expe $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1220,23 +1222,23 @@ public function productPaginationDataProvider() 'expect-all-items' => [ 'pageSize' => 10, 'currentPage' => 1, - 'expectedCount' => 5 + 'expectedCount' => 5, ], 'expect-page=size-items' => [ 'pageSize' => 2, 'currentPage' => 1, - 'expectedCount' => 2 + 'expectedCount' => 2, ], 'expect-less-than-pagesize-elements' => [ 'pageSize' => 3, 'currentPage' => 2, - 'expectedCount' => 2 + 'expectedCount' => 2, ], 'expect-no-items' => [ 'pageSize' => 100, 'currentPage' => 99, - 'expectedCount' => 0 - ] + 'expectedCount' => 0, + ], ]; } @@ -1292,7 +1294,7 @@ public function testGetListWithMultipleFilterGroupsAndSortingAndPagination() $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1311,6 +1313,79 @@ public function testGetListWithMultipleFilterGroupsAndSortingAndPagination() ); } + /** + * Test get list filter by category sorting by position. + * + * @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php + * @dataProvider getListSortingByPositionDataProvider + * + * @param string $sortOrder + * @param array $expectedItems + */ + public function testGetListSortingByPosition(string $sortOrder, array $expectedItems): void + { + $sortOrderBuilder = Bootstrap::getObjectManager()->create(SortOrderBuilder::class); + $searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class); + $sortOrder = $sortOrderBuilder->setField('position')->setDirection($sortOrder)->create(); + $searchCriteriaBuilder->addFilter('category_id', 333); + $searchCriteriaBuilder->addSortOrder($sortOrder); + $searchCriteriaBuilder->setPageSize(5); + $searchCriteriaBuilder->setCurrentPage(1); + $searchData = $searchCriteriaBuilder->create()->__toArray(); + $requestData = ['searchCriteria' => $searchData]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), + 'httpMethod' => Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetList', + ], + ]; + + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertEquals(5, $searchResult['total_count']); + $this->assertEquals($expectedItems[0], $searchResult['items'][0]['sku']); + $this->assertEquals($expectedItems[1], $searchResult['items'][1]['sku']); + $this->assertEquals($expectedItems[2], $searchResult['items'][2]['sku']); + $this->assertEquals($expectedItems[3], $searchResult['items'][3]['sku']); + $this->assertEquals($expectedItems[4], $searchResult['items'][4]['sku']); + } + + /** + * Provides data for testGetListSortingByPosition(). + * + * @return array[] + */ + public function getListSortingByPositionDataProvider(): array + { + return [ + 'sort_by_position_descending' => [ + 'direction' => SortOrder::SORT_DESC, + 'expectedItems' => [ + 'search_product_5', + 'search_product_4', + 'search_product_3', + 'search_product_2', + 'search_product_1', + ], + ], + 'sort_by_position_ascending' => [ + 'direction' => SortOrder::SORT_ASC, + 'expectedItems' => [ + 'search_product_1', + 'search_product_2', + 'search_product_3', + 'search_product_4', + 'search_product_5', + ], + ], + ]; + } + /** * Convert custom attributes to associative array * @@ -1393,7 +1468,7 @@ protected function getSimpleProductData($productData = []) 'custom_attributes' => [ ['attribute_code' => 'cost', 'value' => ''], ['attribute_code' => 'description', 'value' => 'Description'], - ] + ], ]; } @@ -1419,7 +1494,7 @@ protected function saveProduct($product, $storeCode = null, ?string $token = nul $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + 'httpMethod' => Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1446,7 +1521,7 @@ protected function deleteProduct($sku) $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE, + 'httpMethod' => Request::HTTP_METHOD_DELETE, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -1478,7 +1553,7 @@ public function testTierPrices() 'customer_group_id' => $custGroup2, 'value' => 3.45, 'qty' => 10, - ] + ], ]; $this->saveProduct($productData); $response = $this->getProduct($productData[ProductInterface::SKU]); @@ -1587,7 +1662,7 @@ public function testProductCategoryLinks() // Create simple product $productData = $this->getSimpleProductData(); $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = [ - self::KEY_CATEGORY_LINKS => [['category_id' => 333, 'position' => 0]] + self::KEY_CATEGORY_LINKS => [['category_id' => 333, 'position' => 0]], ]; $response = $this->saveProduct($productData); $this->assertEquals( @@ -1634,7 +1709,7 @@ public function testUpdateProductCategoryLinksPosistion() $response = $this->getProduct('simple333'); // update category_link position $response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS] = [ - ['category_id' => 333, 'position' => 10] + ['category_id' => 333, 'position' => 10], ]; $response = $this->updateProduct($response); $this->assertEquals( @@ -1686,7 +1761,7 @@ private function getMediaGalleryData( 'type' => 'image/jpeg', 'name' => $filename, 'base64_encoded_data' => $encodedImage, - ] + ], ]; } @@ -1697,7 +1772,7 @@ public function testSpecialPrice() { $productData = $this->getSimpleProductData(); $productData['custom_attributes'] = [ - ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => '1'] + ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => '1'], ]; $this->saveProduct($productData); $response = $this->getProduct($productData[ProductInterface::SKU]); @@ -1727,14 +1802,14 @@ public function testResetSpecialPrice() ); $productData = $this->getSimpleProductData(); $productData['custom_attributes'] = [ - ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => 5.00] + ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => 5.00], ]; $this->saveProduct($productData); $response = $this->getProduct($productData[ProductInterface::SKU]); $customAttributes = array_column($response['custom_attributes'], 'value', 'attribute_code'); $this->assertEquals(5, $customAttributes[self::KEY_SPECIAL_PRICE]); $productData['custom_attributes'] = [ - ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => null] + ['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => null], ]; $this->saveProduct($productData); $response = $this->getProduct($productData[ProductInterface::SKU]); @@ -1794,7 +1869,7 @@ public function testUpdateMultiselectAttributes() $productData = $this->getSimpleProductData(); $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => "{$option1},{$option2}"] + ['attribute_code' => $multiselectAttributeCode, 'value' => "{$option1},{$option2}"], ]; $this->saveProduct($productData, 'all'); @@ -1805,7 +1880,7 @@ public function testUpdateMultiselectAttributes() ); $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => ""] + ['attribute_code' => $multiselectAttributeCode, 'value' => ""], ]; $this->saveProduct($productData, 'all'); $this->assertMultiselectValue( @@ -1826,7 +1901,7 @@ private function getAttributeOptions($attributeCode) $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/products/attributes/' . $attributeCode . '/options', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => 'catalogProductAttributeOptionManagementV1', @@ -1985,7 +2060,7 @@ public function testImageRolesWithMultipleStores() $this->getMediaGalleryData(basename($img2), $encodedImage, 2, 'back', false, ['small_image', 'thumbnail']), ]; $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY]['website_ids'] = [ - $defaultWebsiteId + $defaultWebsiteId, ]; $response = $this->saveProduct($productData, 'all'); if (isset($response['id'])) { @@ -2062,7 +2137,7 @@ public function testUpdateProductWithMediaGallery(): void $this->getMediaGalleryData(basename($img2), $encodedImage, 2, 'back', false, ['small_image', 'thumbnail']), ]; $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY]['website_ids'] = [ - $defaultWebsiteId + $defaultWebsiteId, ]; $response = $this->saveProduct($productData, 'all'); if (isset($response['id'])) { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_for_search.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_for_search.php index 957fefea77345..abca0865a4cda 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_for_search.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_for_search.php @@ -4,10 +4,12 @@ * See COPYING.txt for license details. */ -use Magento\Catalog\Api\CategoryLinkManagementInterface; +use Magento\Catalog\Api\CategoryLinkRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryProductLinkInterfaceFactory; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Catalog\Model\Product\Visibility; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Workaround\Override\Fixture\Resolver; Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/category.php'); @@ -26,6 +28,7 @@ 'meta_title' => 'Key Title', 'meta_keyword' => 'meta keyword', 'meta_description' => 'meta description', + 'position' => 10, ], [ 'type' => 'simple', @@ -41,6 +44,7 @@ 'meta_title' => 'Last Title', 'meta_keyword' => 'meta keyword', 'meta_description' => 'meta description', + 'position' => 20, ], [ 'type' => 'simple', @@ -56,6 +60,7 @@ 'meta_title' => 'First Title', 'meta_keyword' => 'meta keyword', 'meta_description' => 'meta description', + 'position' => 30, ], [ 'type' => 'simple', @@ -71,6 +76,7 @@ 'meta_title' => 'A title', 'meta_keyword' => 'meta keyword', 'meta_description' => 'meta description', + 'position' => 40, ], [ 'type' => 'simple', @@ -86,18 +92,15 @@ 'meta_title' => 'meta title', 'meta_keyword' => 'meta keyword', 'meta_description' => 'meta description', + 'position' => 50, ], ]; -/** @var CategoryLinkManagementInterface $categoryLinkManagement */ -$categoryLinkManagement = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(CategoryLinkManagementInterface::class); - $categoriesToAssign = []; foreach ($products as $data) { /** @var $product Product */ - $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(Product::class); + $product = Bootstrap::getObjectManager()->create(Product::class); $product ->setTypeId($data['type']) ->setId($data['id']) @@ -114,9 +117,15 @@ ->setStockData(['use_config_manage_stock' => 0]) ->save(); - $categoriesToAssign[$data['sku']][] = $data['category_id']; + $categoriesToAssign[$data['sku']] = ['category_id' => $data['category_id'], 'position' => $data['position']]; } -foreach ($categoriesToAssign as $sku => $categoryIds) { - $categoryLinkManagement->assignProductToCategories($sku, $categoryIds); +$linkFactory = Bootstrap::getObjectManager()->get(CategoryProductLinkInterfaceFactory::class); +$categoryLinkRepository = Bootstrap::getObjectManager()->create(CategoryLinkRepositoryInterface::class); +foreach ($categoriesToAssign as $sku => $categoryData) { + $categoryProductLink = $linkFactory->create(); + $categoryProductLink->setSku($sku); + $categoryProductLink->setCategoryId($categoryData['category_id']); + $categoryProductLink->setPosition($categoryData['position']); + $categoryLinkRepository->save($categoryProductLink); } From a24dce44ce86c4a1981de0c15235eca911c0d8f8 Mon Sep 17 00:00:00 2001 From: "taras.gamanov" <engcom-vendorworker-hotel@adobe.com> Date: Wed, 13 Jan 2021 11:50:34 +0200 Subject: [PATCH 187/242] Test case id has been updated. --- ...StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml index b04ac0f4727d0..f1c3898cb5af7 100644 --- a/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml +++ b/app/code/Magento/Multishipping/Test/Mftf/Test/StoreFrontCheckVatIdAtAccountCreateWithMultishipmentTest.xml @@ -15,7 +15,7 @@ <title value="Checking vat id field at account create page with 'Check Out with Multiple Addresses'"/> <description value="'VAT Number' field should be available at create account page if 'Show VAT Number on Storefront' is Yes"/> <severity value="MAJOR"/> - <testCaseId value="MC-40016"/> + <testCaseId value="MC-40397"/> <group value="Multishipment"/> </annotations> <before> From d62908536f15946ae0263ac76641b29a40036078 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 13 Jan 2021 13:35:17 +0200 Subject: [PATCH 188/242] MC-23729: Invalid date when timeOnly defined on datetime UIComponent. --- app/code/Magento/Ui/view/base/web/js/form/element/date.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js index 9e071e72ca8b7..a5447b290fc5d 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js @@ -181,6 +181,7 @@ define([ this.pickerDateTimeFormat = this.options.timeFormat; } else { this.pickerDateTimeFormat = this.options.dateFormat; + if (this.options.showsTime) { this.pickerDateTimeFormat += ' ' + this.options.timeFormat; } From 8d676bc8f7244e0b5abb5c98c5854dd328f78dc0 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Wed, 13 Jan 2021 14:32:55 +0200 Subject: [PATCH 189/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- .../StorefrontProductInfoMainSection.xml | 2 + ...eoVideoControlButtonsOnProductPageTest.xml | 79 +++++++++++++++++++ lib/web/mage/gallery/gallery.less | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/ProductVideo/Test/Mftf/Section/StorefrontProductInfoMainSection.xml index e94d426ba7638..44c65c197f7db 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Section/StorefrontProductInfoMainSection.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -14,5 +14,7 @@ <element name="videoPausedMode" type="button" selector="//*[contains(@class, 'paused-mode')]"/> <element name="videoPlayedMode" type="button" selector="//*[contains(@class,'playing-mode')]"/> <element name="frameVideo" type="button" selector="widget2"/> + <element name="clickPlayVideo" type="block" selector="//*[contains(@class,'fotorama__stage__shaft')]"/> + <element name="clickCloseVideo" type="block" selector="//*[@class='fotorama__video-close fotorama-show-control']"/> </section> </sections> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml new file mode 100644 index 0000000000000..dab325e19d102 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="VimeoVideoControlButtonsOnProductPageTest"> + <annotations> + <features value="ProductVideo"/> + <stories value="Navigation arrow buttons not visible after video starts on product image"/> + <title value="Navigation arrow buttons not visible after video starts on product image"/> + <description value="Navigation arrow buttons not visible after video starts on product image"/> + <severity value="MAJOR"/> + <testCaseId value="MC-40398"/> + <group value="productVideo"/> + </annotations> + <before> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + <!-- Login to Admin page --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> + <after> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <!-- Logout from Admin page --> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!-- Open product edit page --> + <amOnPage url="{{AdminProductEditPage.url($createProduct.id$)}}" stepKey="goToProductEditPage"/> + <!-- Add image to product --> + <actionGroup ref="AddProductImageActionGroup" stepKey="addImageForProduct"> + <argument name="image" value="MagentoLogo"/> + </actionGroup> + <!-- Add product video --> + <actionGroup ref="AddProductVideoActionGroup" stepKey="addProductVideo"> + <argument name="video" value="VimeoProductVideo"/> + </actionGroup> + <!-- Save product form --> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProductForm"/> + + <!-- Open storefront product page --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="goToStorefrontProductPage"> + <argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/> + </actionGroup> + + <!-- Assert product navigation arrows --> + <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> + <seeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="seeNextButton"/> + <click selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="clickNextButton"/> + + <!-- Assert product video present in the storefront product page --> + <actionGroup ref="AssertProductVideoStorefrontProductPageActionGroup" stepKey="assertProductVideoPresentInStorefrontProductPage"> + <argument name="videoType" value="vimeo"/> + </actionGroup> + <dontSeeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="dontSeeCloseVideo"/> + + <!-- Click Play video button --> + <click stepKey="clickToPlayVideo" selector="{{StorefrontProductInfoMainSection.clickPlayVideo}}"/> + <wait stepKey="waitFiveSecondsToPlayVideo" time="5"/> + + <!-- Assert product navigation arrows --> + <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton2"/> + <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> + + <!-- Click Close video button --> + <seeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="seeCloseVideo"/> + <click stepKey="clickCloseVideo" selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}"/> + <wait stepKey="waitTwoSecondsToCloseVideo" time="2"/> + + <!-- Assert product navigation arrows --> + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <seeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="seePrevButton"/> + <click selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="clickPrevButton"/> + </test> +</tests> diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index 86ccdb858bf19..d6926720d7984 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -964,7 +964,7 @@ height: @fotorama_close_button; opacity: 0; right: 0; - top: 0; + top: 10%; transform: translate3d((@fotorama_close_button), (-@fotorama_close_button), 0); transition: opacity 0.3s ease-in-out; width: @fotorama_close_button; From 081ff88e4eb1b7514911c7ca62c41183c67f6251 Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Wed, 13 Jan 2021 16:29:46 +0200 Subject: [PATCH 190/242] MC-40136: Create automated test for: "Update items stock status and low stock date after save config" --- .../out_of_stock_product_with_category.php | 2 +- .../_files/product_simple_backorders_no.php | 52 +++ .../product_simple_backorders_no_rollback.php | 28 ++ .../Model/ResourceModel/Stock/ItemTest.php | 301 ++++++++++++++++++ 4 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/out_of_stock_product_with_category.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/out_of_stock_product_with_category.php index c38b77d886bfc..774d285e8dcb2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/out_of_stock_product_with_category.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/out_of_stock_product_with_category.php @@ -26,7 +26,7 @@ $product->setTypeId(Type::TYPE_SIMPLE) ->setAttributeSetId($product->getDefaultAttributeSetId()) ->setWebsiteIds([1]) - ->setName('Simple Product Out Of Stock') + ->setName('Simple Product Out Of Stock With Category') ->setSku('out-of-stock-product') ->setPrice(10) ->setWeight(1) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php new file mode 100644 index 0000000000000..34bf9239fbe90 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Helper\DefaultCategory; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\CatalogInventory\Model\Stock; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepositoryFactory */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var ProductFactory $productFactory */ +$productFactory = $objectManager->get(ProductFactory::class); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var DefaultCategory $defaultCategory */ +$defaultCategory = $objectManager->get(DefaultCategory::class); +$defaultWebsiteId = $websiteRepository->get('base')->getId(); +$product = $productFactory->create(); +$product->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([$defaultWebsiteId]) + ->setName('Simple Product Backorders No') + ->setSku('simple-backorders-no') + ->setPrice(20) + ->setWeight(10) + ->setShortDescription('Short description backorders no') + ->setDescription('Description with <b>html tag</b> backorders no') + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setCategoryIds([$defaultCategory->getId()]) + ->setStockData([ + 'use_config_manage_stock' => 1, + 'qty' => 20, + 'is_qty_decimal' => 0, + 'is_in_stock' => Stock::STOCK_IN_STOCK, + 'use_config_backorders' => 0, + 'backorders' => Stock::BACKORDERS_NO, + ]); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no_rollback.php new file mode 100644 index 0000000000000..0fcdbd911cc35 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no_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\Catalog\Api\ProductRepositoryInterface; +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 ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('simple-backorders-no'); +} catch (NoSuchEntityException $e) { + // product already deleted +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php new file mode 100644 index 0000000000000..e003c2cbbc9a5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php @@ -0,0 +1,301 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Model\ResourceModel\Stock; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Indexer\Product\Price\Processor as PriceProcessor; +use Magento\CatalogInventory\Model\Configuration; +use Magento\CatalogInventory\Model\Indexer\Stock\Processor as StockProcessor; +use Magento\CatalogInventory\Model\Stock; +use Magento\CatalogInventory\Model\StockRegistryStorage; +use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\Indexer\StateInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests for stock item resource model + * + * @see \Magento\CatalogInventory\Model\ResourceModel\Stock\Item + */ +class ItemTest extends TestCase +{ + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var MutableScopeConfigInterface */ + private $mutableConfig; + + /** @var Item */ + private $stockItemResource; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var StockRegistryStorage */ + private $stockRegistryStorage; + + /** @var StockProcessor */ + private $stockIndexerProcessor; + + /** @var PriceProcessor */ + private $priceIndexerProcessor; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->mutableConfig = $this->objectManager->get(MutableScopeConfigInterface::class); + $this->stockItemResource = $this->objectManager->get(Item::class); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->productRepository->cleanCache(); + $this->stockRegistryStorage = $this->objectManager->get(StockRegistryStorage::class); + $this->stockIndexerProcessor = $this->objectManager->get(StockProcessor::class); + $this->priceIndexerProcessor = $this->objectManager->get(PriceProcessor::class); + } + + /** + * @dataProvider updateSetOutOfStockDataProvider + * @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php + * @magentoDataFixture Magento/Catalog/_files/product_simple_backorders_no.php + * @magentoConfigFixture default_store cataloginventory/item_options/min_qty 105 + * @magentoConfigFixture default_store cataloginventory/item_options/manage_stock 1 + * @param int $backorders + * @param array $expectedStockItems + * @magentoDbIsolation disabled + * @return void + */ + public function testUpdateSetOutOfStock(int $backorders, array $expectedStockItems): void + { + $this->stockIndexerProcessor->reindexAll(); + $this->priceIndexerProcessor->reindexAll(); + $this->mutableConfig->setValue(Configuration::XML_PATH_BACKORDERS, $backorders, ScopeInterface::SCOPE_STORE); + $websiteId = (int)$this->storeManager->getWebsite('admin')->getId(); + $this->stockItemResource->updateSetOutOfStock($websiteId); + + $this->assertProductsStockItem($expectedStockItems); + $this->assertEquals(StateInterface::STATUS_INVALID, $this->stockIndexerProcessor->getIndexer()->getStatus()); + $this->assertEquals(StateInterface::STATUS_INVALID, $this->priceIndexerProcessor->getIndexer()->getStatus()); + } + + /** + * @return array + */ + public function updateSetOutOfStockDataProvider(): array + { + return [ + 'backorders_no' => [ + 'backorders' => Stock::BACKORDERS_NO, + 'expected_stock_items' => [ + 'simple-1' => [ + 'is_in_stock' => Stock::STOCK_OUT_OF_STOCK, + 'stock_status_changed_auto' => 1, + ], + 'simple-backorders-no' => [ + 'is_in_stock' => Stock::STOCK_OUT_OF_STOCK, + 'stock_status_changed_auto' => 1, + ], + ], + ], + 'backorders_yes' => [ + 'backorders' => Stock::BACKORDERS_YES_NONOTIFY, + 'expected_stock_items' => [ + 'simple-1' => [ + 'is_in_stock' => Stock::STOCK_IN_STOCK, + 'stock_status_changed_auto' => 0, + ], + 'simple-backorders-no' => [ + 'is_in_stock' => Stock::STOCK_OUT_OF_STOCK, + 'stock_status_changed_auto' => 1, + ], + ], + ], + ]; + } + + /** + * @dataProvider updateUpdateSetInStockDataProvider + * @magentoDataFixture Magento/Catalog/_files/out_of_stock_product_with_category.php + * @magentoDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php + * @magentoConfigFixture default_store cataloginventory/item_options/min_qty 50 + * @param int $manageStock + * @param array $expectedStockItems + * @magentoDbIsolation disabled + * @return void + */ + public function testUpdateSetInStock(int $manageStock, array $expectedStockItems): void + { + $this->updateProductsStockItem([ + 'out-of-stock-product' => [ + 'qty' => 60, + 'stock_status_changed_automatically_flag' => true, + ], + 'simple-out-of-stock' => [ + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + 'qty' => 80, + 'stock_status_changed_automatically_flag' => true, + ], + ]); + $this->stockIndexerProcessor->reindexAll(); + $this->priceIndexerProcessor->reindexAll(); + $this->mutableConfig->setValue(Configuration::XML_PATH_MANAGE_STOCK, $manageStock, ScopeInterface::SCOPE_STORE); + $websiteId = (int)$this->storeManager->getWebsite('admin')->getId(); + $this->stockItemResource->updateSetInStock($websiteId); + + $this->assertProductsStockItem($expectedStockItems); + $this->assertEquals(StateInterface::STATUS_INVALID, $this->stockIndexerProcessor->getIndexer()->getStatus()); + $this->assertEquals(StateInterface::STATUS_INVALID, $this->priceIndexerProcessor->getIndexer()->getStatus()); + } + + /** + * @return array + */ + public function updateUpdateSetInStockDataProvider(): array + { + return [ + 'manage_stock_yes' => [ + 'manage_stock' => 1, + 'expected_stock_items' => [ + 'out-of-stock-product' => [ + 'is_in_stock' => Stock::STOCK_IN_STOCK, + ], + 'simple-out-of-stock' => [ + 'is_in_stock' => Stock::STOCK_IN_STOCK, + ], + ], + ], + 'manage_stock_no' => [ + 'manage_stock' => 0, + 'expected_stock_items' => [ + 'out-of-stock-product' => [ + 'is_in_stock' => Stock::STOCK_OUT_OF_STOCK, + ], + 'simple-out-of-stock' => [ + 'is_in_stock' => Stock::STOCK_IN_STOCK, + ], + ], + ], + ]; + } + + /** + * @dataProvider updateLowStockDateDataProvider + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_url_key.php + * @param int $manageStock + * @param array $expectedLowStockDate + * @return void + */ + public function testLowStockDate(int $manageStock, array $expectedLowStockDate): void + { + $this->updateProductsStockItem([ + 'simple2' => [ + 'use_config_manage_stock' => 0, + 'manage_stock' => 1, + ], + ]); + $this->mutableConfig->setValue(Configuration::XML_PATH_MANAGE_STOCK, $manageStock, ScopeInterface::SCOPE_STORE); + $this->mutableConfig->setValue(Configuration::XML_PATH_NOTIFY_STOCK_QTY, 105, ScopeInterface::SCOPE_STORE); + $websiteId = (int)$this->storeManager->getWebsite('admin')->getId(); + $this->stockItemResource->updateLowStockDate($websiteId); + + $this->assertLowStockDate($expectedLowStockDate); + } + + /** + * @return array + */ + public function updateLowStockDateDataProvider(): array + { + return [ + 'manage_stock_yes' => [ + 'manage_stock' => 1, + 'expected_low_stock_date' => [ + 'simple1' => [ + 'is_low_stock_date_null' => false, + ], + 'simple2' => [ + 'is_low_stock_date_null' => false, + ], + ], + ], + 'manage_stock_no' => [ + 'manage_stock' => 0, + 'expected_low_stock_date' => [ + 'simple1' => [ + 'is_low_stock_date_null' => true, + ], + 'simple2' => [ + 'is_low_stock_date_null' => false, + ], + ], + ], + ]; + } + + /** + * Update products stock item + * + * @param array $productsStockData + * @return void + */ + private function updateProductsStockItem(array $productsStockData): void + { + foreach ($productsStockData as $sku => $stockData) { + $product = $this->productRepository->get($sku, true, null, true); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $stockItem->addData($stockData); + $this->productRepository->save($product); + } + } + + /** + * Assert products stock item + * + * @param array $expectedStockItems + * @return void + */ + private function assertProductsStockItem(array $expectedStockItems): void + { + $this->stockRegistryStorage->clean(); + foreach ($expectedStockItems as $sku => $expectedData) { + $product = $this->productRepository->get($sku, false, null, true); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEmpty(array_diff_assoc($expectedData, $stockItem->getData()), 'Actual stock item data not equals expected data.'); + } + } + + /** + * Assert low_stock_date value of products stock item + * + * @param array $expectedLowStockDate + * @return void + */ + private function assertLowStockDate(array $expectedLowStockDate): void + { + $this->stockRegistryStorage->clean(); + foreach ($expectedLowStockDate as $sku => $expectedData) { + $product = $this->productRepository->get($sku, false, null, true); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + if ($expectedData['is_low_stock_date_null']) { + $this->assertNull($stockItem->getLowStockDate()); + } else { + $this->assertNotNull($stockItem->getLowStockDate()); + } + } + } +} From 60ea40d14e68b55904e9d044a9f7866f5aefad0f Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Wed, 13 Jan 2021 16:56:59 +0200 Subject: [PATCH 191/242] MC-39317: Reorder is not working with custom options date for customer created during checkout --- .../Catalog/Model/ProductOptionProcessor.php | 11 ++- .../Controller/Account/CreatePostTest.php | 49 +++++++++++ ..._order_with_product_and_custom_options.php | 88 +++++++++++++++++++ ...th_product_and_custom_options_rollback.php | 11 +++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options_rollback.php diff --git a/app/code/Magento/Catalog/Model/ProductOptionProcessor.php b/app/code/Magento/Catalog/Model/ProductOptionProcessor.php index db9f4de142956..b0ac93942b100 100644 --- a/app/code/Magento/Catalog/Model/ProductOptionProcessor.php +++ b/app/code/Magento/Catalog/Model/ProductOptionProcessor.php @@ -152,6 +152,15 @@ private function getUrlBuilder() */ private function isDateWithDateInternal(array $optionValue): bool { - return array_key_exists('date_internal', $optionValue) && array_key_exists('date', $optionValue); + $hasDate = !empty($optionValue['day']) + && !empty($optionValue['month']) + && !empty($optionValue['year']); + + $hasTime = !empty($optionValue['hour']) + && isset($optionValue['minute']); + + $hasDateInternal = !empty($optionValue['date_internal']); + + return $hasDateInternal && ($hasDate || $hasTime || !empty($optionValue['date'])); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/CreatePostTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/CreatePostTest.php index 8ce1d2ae9ccf9..89fbb451fa45d 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/CreatePostTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Account/CreatePostTest.php @@ -10,12 +10,15 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\Delegation\Storage as DelegatedStorage; use Magento\Framework\App\Http; use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Message\MessageInterface; use Magento\Framework\Stdlib\CookieManagerInterface; use Magento\Framework\UrlInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Item as OrderItem; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Mail\Template\TransportBuilderMock; use Magento\TestFramework\Request; @@ -96,6 +99,52 @@ public function testNoFormKeyCreatePostAction(): void ); } + /** + * Check that DateTime option is NOT changed after creating Customer account for which guest order was placed. + * + * @return void + * @magentoDataFixture Magento/Sales/_files/guest_order_with_product_and_custom_options.php + */ + public function testCreateCustomerAccountAfterIssuingGuestOrder(): void + { + /** @var Order $order */ + $order = $this->_objectManager->create(Order::class); + $order->loadByIncrementId('100000001'); + + /** @var CustomerInterface $customer */ + $customer = $this->_objectManager->create(CustomerInterface::class); + + /** @var DelegatedStorage $delegatedStorage */ + $delegatedStorage = $this->_objectManager->get(DelegatedStorage::class); + $delegatedStorage->storeNewOperation($customer, ['__sales_assign_order_id' => $order->getId()]); + + $this->fillRequestWithAccountData('customer@example.com'); + $this->dispatch('customer/account/createPost'); + + $this->assertRedirect($this->stringEndsWith('customer/account/')); + $this->assertSessionMessages( + $this->containsEqual( + (string)__('Thank you for registering with %1.', $this->storeManager->getStore()->getFrontendName()) + ), + MessageInterface::TYPE_SUCCESS + ); + + $expectedResult = [ + 'year' => '2021', + 'month' => '9', + 'day' => '9', + 'hour' => '2', + 'minute' => '2', + 'day_part' => 'am', + 'date_internal' => '2021-09-09 02:02:00', + ]; + /** @var OrderItem $orderItem */ + $orderItem = $order->getItemsCollection()->getFirstItem(); + $actualResult = current($orderItem->getBuyRequest()->getOptions()); + $this->assertIsArray($actualResult); + $this->assertEquals($expectedResult, $actualResult); + } + /** * @magentoDbIsolation enabled * @magentoAppIsolation enabled diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options.php b/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options.php new file mode 100644 index 0000000000000..0660cffb76721 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Model\ProductRepository; +use Magento\Sales\Api\Data\OrderAddressInterface; +use Magento\Sales\Api\Data\OrderPaymentInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Item as OrderItem; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php'); + +$addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php'; + +$objectManager = Bootstrap::getObjectManager(); +/** @var OrderAddressInterface $billingAddress */ +$billingAddress = $objectManager->create(OrderAddressInterface::class, ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +/** @var OrderPaymentInterface $payment */ +$payment = $objectManager->create(OrderPaymentInterface::class); +$payment->setMethod('checkmo'); + +/** @var ProductRepository $productRepository */ +$productRepository = $objectManager->get(ProductRepository::class); +$productRepository->cleanCache(); + +$optionValuesByType = [ + 'field' => 'Test value', + 'date_time' => [ + 'year' => '2021', + 'month' => '9', + 'day' => '9', + 'hour' => '2', + 'minute' => '2', + 'day_part' => 'am', + 'date_internal' => '2021-09-09 02:02:00', + ], + 'drop_down' => '3-1-select', + 'radio' => '4-1-radio', +]; + +$requestInfo = ['options' => []]; +$product = $productRepository->get('simple'); +$productOptions = $product->getOptions(); +foreach ($productOptions as $option) { + $requestInfo['options'][$option->getOptionId()] = $optionValuesByType[$option->getType()]; +} + +/** @var OrderItem $orderItem */ +$orderItem = $objectManager->create(OrderItem::class); +$orderItem->setProductId($product->getId()); +$orderItem->setSku($product->getSku()); +$orderItem->setQtyOrdered(1); +$orderItem->setBasePrice($product->getPrice()); +$orderItem->setPrice($product->getPrice()); +$orderItem->setRowTotal($product->getPrice()); +$orderItem->setProductType($product->getTypeId()); +$orderItem->setProductOptions(['info_buyRequest' => $requestInfo]); + +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000001'); +$order->setState(Order::STATE_NEW); +$order->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_NEW)); +$order->setCustomerIsGuest(true); +$order->setCustomerEmail('customer@example.com'); +$order->setCustomerFirstname('firstname'); +$order->setCustomerLastname('lastname'); +$order->setBillingAddress($billingAddress); +$order->setShippingAddress($shippingAddress); +$order->setAddresses([$billingAddress, $shippingAddress]); +$order->setPayment($payment); +$order->addItem($orderItem); +$order->setStoreId($objectManager->get(StoreManagerInterface::class)->getStore()->getId()); +$order->setSubtotal(100); +$order->setBaseSubtotal(100); +$order->setBaseGrandTotal(100); +$order->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options_rollback.php new file mode 100644 index 0000000000000..846573e6d6938 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/guest_order_with_product_and_custom_options_rollback.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Sales/_files/default_rollback.php'); From 08bfb7519d5ebaa8e723fed3595d82957e6d646f Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Wed, 13 Jan 2021 16:59:17 +0200 Subject: [PATCH 192/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- ...oseButtonHiddenProductVideoActionGroup.xml | 19 ++++++++++++ ...extButtonHiddenProductVideoActionGroup.xml | 20 +++++++++++++ ...revButtonHiddenProductVideoActionGroup.xml | 20 +++++++++++++ ...lickCloseButtonProductVideoActionGroup.xml | 21 +++++++++++++ ...ClickNextButtonProductVideoActionGroup.xml | 21 +++++++++++++ ...ClickPlayButtonProductVideoActionGroup.xml | 20 +++++++++++++ ...ClickPrevButtonProductVideoActionGroup.xml | 21 +++++++++++++ ...eoVideoControlButtonsOnProductPageTest.xml | 30 ++++++++----------- 8 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml new file mode 100644 index 0000000000000..edd837db6c31c --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.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"> + <!-- Assert that close button is hidden on Storefront Product page --> + <actionGroup name="AssertCloseButtonHiddenProductVideoActionGroup"> + <annotations> + <description>Validates that the close button is absent on the Storefront Product page.</description> + </annotations> + + <dontSeeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="dontSeeCloseVideo"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml new file mode 100644 index 0000000000000..d6d756847e0b7 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.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"> + <!-- Assert that next button is hidden on Storefront Product page --> + <actionGroup name="AssertNextButtonHiddenProductVideoActionGroup"> + <annotations> + <description>Validates that the next button is absent on the Storefront Product page.</description> + </annotations> + + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml new file mode 100644 index 0000000000000..b5b9e801d3a9c --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.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"> + <!-- Assert that previous button is hidden on Storefront Product page --> + <actionGroup name="AssertPrevButtonHiddenProductVideoActionGroup"> + <annotations> + <description>Validates that the previous button is absent on the Storefront Product page.</description> + </annotations> + + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml new file mode 100644 index 0000000000000..a18e98eebb48c --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.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"> + <!-- Click close button in product video on Storefront Product page --> + <actionGroup name="ClickCloseButtonProductVideoActionGroup"> + <annotations> + <description>Click close button in product video on the Storefront Product page.</description> + </annotations> + + <seeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="seeCloseVideo"/> + <click stepKey="clickCloseVideo" selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}"/> + <wait stepKey="waitTwoSecondsToCloseVideo" time="2"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml new file mode 100644 index 0000000000000..eb7c94514fa24 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.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"> + <!-- Click next button in product video on Storefront Product page --> + <actionGroup name="ClickNextButtonProductVideoActionGroup"> + <annotations> + <description>Click next button in product video on the Storefront Product page.</description> + </annotations> + + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <seeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="seeNextButton"/> + <click selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="clickNextButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml new file mode 100644 index 0000000000000..481097b488be8 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.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"> + <!-- Click play button in product video on Storefront Product page --> + <actionGroup name="ClickPlayButtonProductVideoActionGroup"> + <annotations> + <description>Click play button in product video on the Storefront Product page.</description> + </annotations> + + <click selector="{{StorefrontProductInfoMainSection.clickPlayVideo}}" stepKey="clickToPlayVideo"/> + <wait stepKey="waitFiveSecondsToPlayVideo" time="5"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml new file mode 100644 index 0000000000000..aa32812997624 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.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"> + <!-- Click previous button in product video on Storefront Product page --> + <actionGroup name="ClickPrevButtonProductVideoActionGroup"> + <annotations> + <description>Click previous button in product video on the Storefront Product page.</description> + </annotations> + + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <seeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="seePrevButton"/> + <click selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="clickPrevButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml index dab325e19d102..c86b11660bef8 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml @@ -30,7 +30,9 @@ </after> <!-- Open product edit page --> - <amOnPage url="{{AdminProductEditPage.url($createProduct.id$)}}" stepKey="goToProductEditPage"/> + <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProductEditPage"> + <argument name="productId" value="$createProduct.id$"/> + </actionGroup> <!-- Add image to product --> <actionGroup ref="AddProductImageActionGroup" stepKey="addImageForProduct"> <argument name="image" value="MagentoLogo"/> @@ -47,33 +49,27 @@ <argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/> </actionGroup> - <!-- Assert product navigation arrows --> - <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> - <seeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="seeNextButton"/> - <click selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="clickNextButton"/> + <!-- Click next button --> + <actionGroup ref="AssertPrevButtonHiddenProductVideoActionGroup" stepKey="assertPrevButtonIsHidden"/> + <actionGroup ref="ClickNextButtonProductVideoActionGroup" stepKey="clickNextNavigationButton"/> <!-- Assert product video present in the storefront product page --> <actionGroup ref="AssertProductVideoStorefrontProductPageActionGroup" stepKey="assertProductVideoPresentInStorefrontProductPage"> <argument name="videoType" value="vimeo"/> </actionGroup> - <dontSeeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="dontSeeCloseVideo"/> + <actionGroup ref="AssertCloseButtonHiddenProductVideoActionGroup" stepKey="assertCloseVideoButtonIsHidden"/> <!-- Click Play video button --> - <click stepKey="clickToPlayVideo" selector="{{StorefrontProductInfoMainSection.clickPlayVideo}}"/> - <wait stepKey="waitFiveSecondsToPlayVideo" time="5"/> + <actionGroup ref="ClickPlayButtonProductVideoActionGroup" stepKey="clickPlayVideoButton"/> <!-- Assert product navigation arrows --> - <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton2"/> - <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> + <actionGroup ref="AssertPrevButtonHiddenProductVideoActionGroup" stepKey="assertPrevButtonIsHidden2"/> + <actionGroup ref="AssertNextButtonHiddenProductVideoActionGroup" stepKey="assertNextButtonIsHidden"/> <!-- Click Close video button --> - <seeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="seeCloseVideo"/> - <click stepKey="clickCloseVideo" selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}"/> - <wait stepKey="waitTwoSecondsToCloseVideo" time="2"/> + <actionGroup ref="ClickCloseButtonProductVideoActionGroup" stepKey="clickCloseVideoButton"/> - <!-- Assert product navigation arrows --> - <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> - <seeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="seePrevButton"/> - <click selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="clickPrevButton"/> + <!-- Click previous button --> + <actionGroup ref="ClickPrevButtonProductVideoActionGroup" stepKey="clickPrevNavigationButton"/> </test> </tests> From 5b94d69af88c7693834612c8c4e1a6882aab84fb Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Wed, 13 Jan 2021 17:10:57 +0200 Subject: [PATCH 193/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- .../Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml index c86b11660bef8..a4719fa281f29 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml @@ -16,6 +16,7 @@ <description value="Navigation arrow buttons not visible after video starts on product image"/> <severity value="MAJOR"/> <testCaseId value="MC-40398"/> + <useCaseId value="MC-39759"/> <group value="productVideo"/> </annotations> <before> From 1436ea08276e9de5c364aab00d8f8a5f140944ec Mon Sep 17 00:00:00 2001 From: Vitalii Zabaznov <vzabaznov@magento.com> Date: Wed, 13 Jan 2021 10:09:28 -0600 Subject: [PATCH 194/242] MCP-89: Move product batch size variable to environment --- .../Product/Indexer/Price/BatchSizeCalculatorTest.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculatorTest.php index 589bdf8dda076..d813bb0e5caaa 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculatorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Indexer/Price/BatchSizeCalculatorTest.php @@ -12,6 +12,7 @@ use Magento\Framework\Indexer\BatchSizeManagementInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Magento\Framework\App\DeploymentConfig; class BatchSizeCalculatorTest extends TestCase { @@ -30,6 +31,11 @@ class BatchSizeCalculatorTest extends TestCase */ private $batchRowsCount; + /** + * @var DeploymentConfig|MockObject + */ + private $deploymentConfigMock; + protected function setUp(): void { $this->estimatorMock = $this->getMockForAbstractClass(BatchSizeManagementInterface::class); @@ -37,7 +43,8 @@ protected function setUp(): void $this->model = new BatchSizeCalculator( ['default' => $this->batchRowsCount], ['default' => $this->estimatorMock], - [] + [], + $this->createMock(DeploymentConfig::class) ); } From 8ae0c79c375bcad0863e5885847222411f985c6c Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Wed, 13 Jan 2021 18:38:19 +0200 Subject: [PATCH 195/242] fixing conflicts --- ...dminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 6729f07825dce..7b89492cbb574 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -84,17 +84,12 @@ <seeInField selector="{{AdminProductFormSection.productQuantity}}" userInput="{{simpleProductRegularPrice32503OutOfStock.quantity}}" stepKey="seeSimpleProductQuantity"/> <seeInField selector="{{AdminProductFormSection.productStockStatus}}" userInput="{{simpleProductRegularPrice32503OutOfStock.status}}" stepKey="seeSimpleProductStockStatus"/> <seeInField selector="{{AdminProductFormSection.productWeight}}" userInput="{{simpleProductRegularPrice32503OutOfStock.weight}}" stepKey="seeSimpleProductWeight"/> -<<<<<<< HEAD - <click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="clickCategoriesDropDownToVerify"/> - <see selector="{{AdminProductFormSection.selectMultipleCategories}}" userInput="$$categoryEntity.name$$" stepKey="selectedCategories"/> -======= <comment userInput="Comment is added to preserve the step key for backward compatibility" stepKey="clickCategoriesDropDownToVerify"/> <actionGroup ref="AssertAdminProductIsAssignedToCategoryActionGroup" stepKey="selectedCategories"> <argument name="categoryName" value="$$categoryEntity.name$$"/> </actionGroup> ->>>>>>> 2.4-develop <scrollTo selector="{{AdminProductSEOSection.sectionHeader}}" x="0" y="-80" stepKey="scrollToAdminProductSEOSection1"/> <click selector="{{AdminProductSEOSection.sectionHeader}}" stepKey="clickAdminProductSEOSection1"/> <seeInField selector="{{AdminProductSEOSection.urlKeyInput}}" userInput="{{simpleProductRegularPrice32503OutOfStock.urlKey}}" stepKey="seeUrlKey"/> From e4673316adb46c6660fe2f2a3928c644bd8245bd Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Wed, 13 Jan 2021 18:57:59 +0200 Subject: [PATCH 196/242] MC-36149: [CLOUD] 'Be the first to review this product' link is not changed after admin has approved the review --- .../Review/Block/Product/ReviewRenderer.php | 55 +++++++++++------ .../AppendSummaryDataToObjectByEntityCode.php | 59 +++++++++++++++++++ .../Magento/Review/Model/ReviewSummary.php | 3 + 3 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php diff --git a/app/code/Magento/Review/Block/Product/ReviewRenderer.php b/app/code/Magento/Review/Block/Product/ReviewRenderer.php index 0fd6327e1f777..c6987a4ee35c1 100644 --- a/app/code/Magento/Review/Block/Product/ReviewRenderer.php +++ b/app/code/Magento/Review/Block/Product/ReviewRenderer.php @@ -1,7 +1,5 @@ <?php /** - * Review renderer - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -11,13 +9,21 @@ use Magento\Catalog\Block\Product\ReviewRendererInterface; use Magento\Catalog\Model\Product; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\Template\Context; +use Magento\Review\Model\AppendSummaryDataToObjectByEntityCodeFactory; +use Magento\Review\Model\Review; +use Magento\Review\Model\ReviewFactory; use Magento\Review\Model\ReviewSummaryFactory; use Magento\Review\Observer\PredispatchReviewObserver; +use Magento\Store\Model\ScopeInterface; /** - * Class ReviewRenderer + * Review renderer */ -class ReviewRenderer extends \Magento\Framework\View\Element\Template implements ReviewRendererInterface +class ReviewRenderer extends Template implements ReviewRendererInterface { /** * Array of available template name @@ -32,7 +38,7 @@ class ReviewRenderer extends \Magento\Framework\View\Element\Template implements /** * Review model factory * - * @var \Magento\Review\Model\ReviewFactory + * @var ReviewFactory */ protected $_reviewFactory; @@ -42,20 +48,29 @@ class ReviewRenderer extends \Magento\Framework\View\Element\Template implements private $reviewSummaryFactory; /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Review\Model\ReviewFactory $reviewFactory + * @var AppendSummaryDataToObjectByEntityCodeFactory + */ + private $appendSummaryDataToObjectByEntityCodeFactory; + + /** + * @param Context $context + * @param ReviewFactory $reviewFactory * @param array $data - * @param ReviewSummaryFactory $reviewSummaryFactory + * @param ReviewSummaryFactory|null $reviewSummaryFactory + * @param AppendSummaryDataToObjectByEntityCodeFactory|null $appendSummaryDataToObjectByEntityCodeFactory */ public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Review\Model\ReviewFactory $reviewFactory, + Context $context, + ReviewFactory $reviewFactory, array $data = [], - ReviewSummaryFactory $reviewSummaryFactory = null + ReviewSummaryFactory $reviewSummaryFactory = null, + AppendSummaryDataToObjectByEntityCodeFactory $appendSummaryDataToObjectByEntityCodeFactory = null ) { $this->_reviewFactory = $reviewFactory; $this->reviewSummaryFactory = $reviewSummaryFactory ?? ObjectManager::getInstance()->get(ReviewSummaryFactory::class); + $this->appendSummaryDataToObjectByEntityCodeFactory = $appendSummaryDataToObjectByEntityCodeFactory ?? + ObjectManager::getInstance()->get(AppendSummaryDataToObjectByEntityCodeFactory::class); parent::__construct($context, $data); } @@ -68,7 +83,7 @@ public function isReviewEnabled(): string { return $this->_scopeConfig->getValue( PredispatchReviewObserver::XML_PATH_REVIEW_ACTIVE, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ); } @@ -80,19 +95,21 @@ public function isReviewEnabled(): string * @param bool $displayIfNoReviews * * @return string - * @throws \Magento\Framework\Exception\LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws LocalizedException + * @throws NoSuchEntityException */ public function getReviewsSummaryHtml( - \Magento\Catalog\Model\Product $product, + Product $product, $templateType = self::DEFAULT_VIEW, $displayIfNoReviews = false ) { if ($product->getRatingSummary() === null) { - $this->reviewSummaryFactory->create()->appendSummaryDataToObject( - $product, - $this->_storeManager->getStore()->getId() - ); + $this->appendSummaryDataToObjectByEntityCodeFactory->create() + ->execute( + $product, + $this->_storeManager->getStore()->getId(), + Review::ENTITY_PRODUCT_CODE + ); } if (null === $product->getRatingSummary() && !$displayIfNoReviews) { diff --git a/app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php b/app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php new file mode 100644 index 0000000000000..6307a86b2c49a --- /dev/null +++ b/app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Review\Model; + +use Magento\Framework\Model\AbstractModel; +use Magento\Review\Model\ResourceModel\Review\Summary\CollectionFactory as SummaryCollectionFactory; + +/** + * Add review summary data to object by its entity code + */ +class AppendSummaryDataToObjectByEntityCode +{ + /** + * @var SummaryCollectionFactory + */ + private $summaryCollectionFactory; + + /** + * @param SummaryCollectionFactory $summaryCollectionFactory + */ + public function __construct( + SummaryCollectionFactory $summaryCollectionFactory + ) { + $this->summaryCollectionFactory = $summaryCollectionFactory; + } + + /** + * @param AbstractModel $object + * @param int $storeId + * @param string $entityCode + * @retrun void + */ + public function execute(AbstractModel $object, int $storeId, string $entityCode): void + { + $summaryCollection = $this->summaryCollectionFactory->create(); + $summaryCollection->addStoreFilter($storeId); + $summaryCollection->getSelect() + ->joinLeft( + ['review_entity' => $summaryCollection->getResource()->getTable('review_entity')], + 'main_table.entity_type = review_entity.entity_id', + 'entity_code' + ) + ->where('entity_pk_value IN (?)', $object->getId()) + ->where('entity_code = ?', $entityCode); + $summaryItem = $summaryCollection->getFirstItem(); + + $object->addData( + [ + 'reviews_count' => $summaryItem->getData('reviews_count'), + 'rating_summary' => $summaryItem->getData('rating_summary'), + ] + ); + } +} diff --git a/app/code/Magento/Review/Model/ReviewSummary.php b/app/code/Magento/Review/Model/ReviewSummary.php index 46851339ae6d7..ff1a2c4e3a76e 100644 --- a/app/code/Magento/Review/Model/ReviewSummary.php +++ b/app/code/Magento/Review/Model/ReviewSummary.php @@ -12,6 +12,9 @@ /** * ReviewSummary model. + * + * @deprecated Filtering collection by entity_type ID leads to wrong result if AUTO_INCREMENT begins not form 1. + * @see \Magento\Review\Model\AppendSummaryDataToObjectByEntityCode */ class ReviewSummary { From 21d42cbb94bb8b6c331b540f75504bace159e7df Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 13 Jan 2021 11:19:18 -0600 Subject: [PATCH 197/242] B2B-1640: Add MFTF test for MC-38222 - Adding MFTF import test for MC-38222 --- ...efrontNavigateToCategoryUrlActionGroup.xml | 18 ++ ...geSelectDropDownOptionValueActionGroup.xml | 1 + .../Section/AdminProductImagesSection.xml | 1 + .../AdminClickCheckDataImportActionGroup.xml | 19 ++ .../AdminClickImportActionGroup.xml | 20 ++ .../AdminFillImportFormActionGroup.xml | 30 +++ .../AdminNavigateToImportPageActionGroup.xml | 17 ++ .../Test/Mftf/Data/ImportData.xml | 98 +++++++++ ...igurableProductsWithAssignedImagesTest.xml | 193 ++++++++++++++++++ 9 files changed, 397 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateToCategoryUrlActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickCheckDataImportActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickImportActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminFillImportFormActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportPageActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateToCategoryUrlActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateToCategoryUrlActionGroup.xml new file mode 100644 index 0000000000000..f938627886540 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontNavigateToCategoryUrlActionGroup.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="StorefrontNavigateToCategoryUrlActionGroup"> + <annotations> + <description>Goes to the Storefront Category page for the provided Category URL.</description> + </annotations> + <arguments> + <argument name="categoryUrl" type="string"/> + </arguments> + <amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="goToStorefrontCategoryPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageSelectDropDownOptionValueActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageSelectDropDownOptionValueActionGroup.xml index 31b18e1f0d37e..9cb3f3faf2f33 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageSelectDropDownOptionValueActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageSelectDropDownOptionValueActionGroup.xml @@ -18,5 +18,6 @@ </arguments> <selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect(attributeLabel)}}" userInput="{{optionLabel}}" stepKey="fillDropDownAttributeOption"/> + <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml index c2de91aadbc0c..0d26c43d2c34b 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml @@ -13,6 +13,7 @@ <element name="imageFileUpload" type="input" selector="#fileupload"/> <element name="imageUploadButton" type="button" selector="div.image div.fileinput-button"/> <element name="imageFile" type="text" selector="//*[@id='media_gallery_content']//img[contains(@src, '{{url}}')]" parameterized="true"/> + <element name="imageElement" type="text" selector="#media_gallery_content img"/> <element name="removeImageButton" type="button" selector=".action-remove"/> <element name="removeImageButtonForExactImage" type="button" selector="[id='media_gallery_content'] img[src*='{{imageName}}'] + div[class='actions'] button[class='action-remove']" parameterized="true"/> <element name="modalOkBtn" type="button" selector="button.action-primary.action-accept"/> diff --git a/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickCheckDataImportActionGroup.xml b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickCheckDataImportActionGroup.xml new file mode 100644 index 0000000000000..4b072e0c60a31 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickCheckDataImportActionGroup.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="AdminClickCheckDataImportActionGroup"> + <annotations> + <description>Clicks the 'Check Data' button on the Admin Import page.</description> + </annotations> + <waitForElementVisible selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="waitForCheckDataButton"/> + <click selector="{{AdminImportHeaderSection.checkDataButton}}" stepKey="clickCheckDataButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickImportActionGroup.xml b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickImportActionGroup.xml new file mode 100644 index 0000000000000..2e64c35d8c822 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminClickImportActionGroup.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="AdminClickImportActionGroup"> + <annotations> + <description>Clicks the 'Import' button on the Admin Import page.</description> + </annotations> + <waitForElementVisible selector="{{AdminImportMainSection.importButton}}" stepKey="waitForImportButton"/> + <click selector="{{AdminImportMainSection.importButton}}" stepKey="clickImportButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForElementVisible selector="{{AdminImportValidationMessagesSection.notice}}" stepKey="waitForNoticeMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminFillImportFormActionGroup.xml b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminFillImportFormActionGroup.xml new file mode 100644 index 0000000000000..a15c58b4d2b2e --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminFillImportFormActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminFillImportFormActionGroup"> + <annotations> + <description>Fills the form on the System > Data Transfer > Import page.</description> + </annotations> + <arguments> + <argument name="entityType" defaultValue="Products" type="string"/> + <argument name="importBehavior" defaultValue="Add/Update" type="string"/> + <argument name="validationStrategy" defaultValue="Stop on Error" type="string" /> + <argument name="allowedErrorsCount" defaultValue="10" type="string" /> + <argument name="importFile" type="string"/> + </arguments> + <waitForElementVisible selector="{{AdminImportMainSection.entityType}}" stepKey="waitForEntityType"/> + <selectOption selector="{{AdminImportMainSection.entityType}}" userInput="{{entityType}}" stepKey="selectEntityType"/> + <waitForElementVisible selector="{{AdminImportMainSection.importBehavior}}" stepKey="waitForImportBehavior"/> + <selectOption selector="{{AdminImportMainSection.importBehavior}}" userInput="{{importBehavior}}" stepKey="selectImportBehaviorOption"/> + <selectOption selector="{{AdminImportMainSection.validationStrategy}}" userInput="{{validationStrategy}}" stepKey="selectValidationStrategyOption"/> + <fillField selector="{{AdminImportMainSection.allowedErrorsCount}}" userInput="{{allowedErrorsCount}}" stepKey="fillAllowedErrorsCountField"/> + <attachFile selector="{{AdminImportMainSection.selectFileToImport}}" userInput="{{importFile}}" stepKey="attachFileForImport"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportPageActionGroup.xml b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportPageActionGroup.xml new file mode 100644 index 0000000000000..03c2fea998991 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportPageActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNavigateToImportPageActionGroup"> + <annotations> + <description>Navigates to the admin System > Data Transfer > Import page.</description> + </annotations> + <amOnPage url="{{AdminImportIndexPage.url}}" stepKey="navigateToImportPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml b/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml new file mode 100644 index 0000000000000..6160a12223552 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml @@ -0,0 +1,98 @@ +<?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"> + <!-- Categories --> + <entity name="Import1" type="category"> + <data key="name">Import1</data> + <data key="name_lwr">import1</data> + <data key="is_active">true</data> + <data key="include_in_menu">true</data> + </entity> + + <!-- Products --> + <entity name="ImportSimple1" type="product"> + <data key="name">import-simple1</data> + <data key="sku">import-simple1</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="price">12.00</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="quantity">100</data> + <data key="urlKey">import-simple1</data> + <data key="weight">12</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + <entity name="ImportSimple2" type="product"> + <data key="name">import-simple2</data> + <data key="sku">import-simple2</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="price">15.00</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="quantity">100</data> + <data key="urlKey">import-simple2</data> + <data key="weight">12</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + <entity name="ImportSimple3" type="product"> + <data key="name">import-simple3</data> + <data key="sku">import-simple3</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="price">10.00</data> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="quantity">100</data> + <data key="urlKey">import-simple3</data> + <data key="weight">12</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + <entity name="ImportConfigurable" type="product"> + <data key="name">import-configurable</data> + <data key="sku">import-configurable</data> + <data key="type_id">configurable</data> + <data key="attribute_set_id">4</data> + <data key="price"/> + <data key="visibility">4</data> + <data key="status">1</data> + <data key="quantity"/> + <data key="urlKey">import-configurable</data> + <data key="weight">12</data> + <requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity> + <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> + </entity> + + <!-- Product Attributes --> + <entity name="ProductAttributeFrontendLabelImport1" type="FrontendLabel"> + <data key="store_id">0</data> + <data key="label">import_attribute1</data> + </entity> + <entity name="ProductAttributeWithThreeOptionsForImport" extends="productAttributeDropdownTwoOptions" type="ProductAttribute"> + <data key="attribute_code">import_attribute1</data> + <requiredEntity type="FrontendLabel">ProductAttributeFrontendLabelImport1</requiredEntity> + </entity> + <entity name="ProductAttributeOptionThreeForImport" extends="productAttributeOption3" type="ProductAttributeOption"> + <data key="label">option3</data> + </entity> + + <!-- Images --> + <entity name="TestImageImageContentExportImport" extends="TestImageContent" type="ImageContent"> + <data key="name">test_image.jpg</data> + </entity> + <entity name="ApiProductAttributeMediaGalleryForExportImport2" extends="ApiProductAttributeMediaGalleryEntryTestImage" type="ProductAttributeMediaGalleryEntry"> + <data key="label">Test Image</data> + <requiredEntity type="ImageContent">TestImageImageContentExportImport</requiredEntity> + </entity> +</entities> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml new file mode 100644 index 0000000000000..8d19407d05c55 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -0,0 +1,193 @@ +<?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="AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest"> + <annotations> + <features value="Import/Export"/> + <stories value="Import Products"/> + <title value="Import Configurable Product With Simple Child Products With Images"/> + <description value="Imports a .csv file containing a configurable product with 3 child simple products that + have images. Verifies that products are imported successfully and that the images are attached to the + products as expected."/> + <severity value="MAJOR"/> + <testCaseId value="MC-38222"/> + <group value="importExport"/> + </annotations> + + <before> + <!-- Create Product Attribute with 3 Options --> + <createData entity="ProductAttributeWithThreeOptionsForImport" stepKey="createImportProductAttribute"/> + <createData entity="ProductAttributeOptionOneForExportImport" stepKey="createImportProductAttributeOption1"> + <requiredEntity createDataKey="createImportProductAttribute"/> + </createData> + <createData entity="ProductAttributeOptionTwoForExportImport" stepKey="createImportProductAttributeOption2"> + <requiredEntity createDataKey="createImportProductAttribute"/> + </createData> + <createData entity="ProductAttributeOptionThreeForImport" stepKey="createImportProductAttributeOption3"> + <requiredEntity createDataKey="createImportProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="addToProductAttributeSet"> + <requiredEntity createDataKey="createImportProductAttribute"/> + </createData> + + <!-- Create a Product & Attach a JPG & PNG --> + <createData entity="Import1" stepKey="createImportCategory"/> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="ApiSimpleProduct" stepKey="productForImages"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ApiProductAttributeMediaGalleryForExportImport" stepKey="productImage1"> + <requiredEntity createDataKey="productForImages"/> + </createData> + <createData entity="ApiProductAttributeMediaGalleryForExportImport2" stepKey="productImage2"> + <requiredEntity createDataKey="productForImages"/> + </createData> + + <!-- Login as Admin --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> + + <after> + <!-- Delete Data --> + <deleteData createDataKey="createImportCategory" stepKey="deleteImportCategory"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <deleteData createDataKey="productForImages" stepKey="deleteProductForImages"/> + <deleteData url="/V1/products/{{ImportSimple1.urlKey}}" stepKey="deleteImportedSimpleProduct1"/> + <deleteData url="/V1/products/{{ImportSimple2.urlKey}}" stepKey="deleteImportedSimpleProduct2"/> + <deleteData url="/V1/products/{{ImportSimple3.urlKey}}" stepKey="deleteImportedSimpleProduct3"/> + <deleteData url="/V1/products/{{ImportConfigurable.urlKey}}" stepKey="deleteImportedConfigurableProduct"/> + <deleteData createDataKey="createImportProductAttribute" stepKey="deleteProductAttribute"/> + <actionGroup ref="NavigateToAndResetProductGridToDefaultViewActionGroup" stepKey="navigateToAndResetProductGridToDefaultView"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <!-- Import Configurable Product with Simple Child Products & Assert No Errors --> + <actionGroup ref="AdminNavigateToImportPageActionGroup" stepKey="navigateToImportPage"/> + <actionGroup ref="AdminFillImportFormActionGroup" stepKey="fillImportForm"> + <argument name="importFile" value="configurable_and_simple_child_products.csv"/> + </actionGroup> + <actionGroup ref="AdminClickCheckDataImportActionGroup" stepKey="clickCheckData"/> + <see selector="{{AdminImportValidationMessagesSection.success}}" userInput="File is valid! To start import process press "Import" button" stepKey="seeCheckDataResultMessage"/> + <dontSeeElementInDOM selector="{{AdminImportValidationMessagesSection.importErrorList}}" stepKey="dontSeeErrorMessage"/> + <actionGroup ref="AdminClickImportActionGroup" stepKey="clickImport"/> + <see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="Created: 4, Updated: 0, Deleted: 0" stepKey="seeNoticeMessage"/> + <see selector="{{AdminImportValidationMessagesSection.messageByType('success')}}" userInput="Import successfully done" stepKey="seeImportMessage"/> + <dontSeeElementInDOM selector="{{AdminImportValidationMessagesSection.importErrorList}}" stepKey="dontSeeErrorMessage2"/> + + <!-- Admin: Verify Simple Product 1 on Product Index Page --> + <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct1InAdminGrid"> + <argument name="product" value="ImportSimple1"/> + </actionGroup> + <seeNumberOfElements selector="{{AdminProductGridSection.productGridRows}}" userInput="1" stepKey="seeOnly1Product"/> + + <!-- Admin: Verify Simple Product 1 on Edit Product Page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="assertSimpleProduct1OnEditPage"> + <argument name="product" value="ImportSimple1"/> + </actionGroup> + <actionGroup ref="AssertProductImageAdminProductPageActionGroup" stepKey="assertProduct1ImageOnEditPage"> + <argument name="image" value="MagentoLogo"/> + </actionGroup> + + <!-- Admin: Verify Simple Product 2 on Product Index Page --> + <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct2InAdminGrid"> + <argument name="product" value="ImportSimple2"/> + </actionGroup> + <seeNumberOfElements selector="{{AdminProductGridSection.productGridRows}}" userInput="1" stepKey="seeOnly1Product2"/> + + <!-- Admin: Verify Simple Product 2 on Edit Product Page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="assertSimpleProduct2OnEditPage"> + <argument name="product" value="ImportSimple2"/> + </actionGroup> + <actionGroup ref="AssertProductImageAdminProductPageActionGroup" stepKey="assertProduct2ImageOnEditPage"> + <argument name="image" value="TestImage"/> + </actionGroup> + + <!-- Admin: Verify Simple Product 3 on Product Index Page --> + <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct3InAdminGrid"> + <argument name="product" value="ImportSimple3"/> + </actionGroup> + <seeNumberOfElements selector="{{AdminProductGridSection.productGridRows}}" userInput="1" stepKey="seeOnly1Product3"/> + + <!-- Admin: Verify Simple Product 3 on Edit Product Page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="assertSimpleProduct3OnEditPage"> + <argument name="product" value="ImportSimple3"/> + </actionGroup> + <actionGroup ref="ExpandAdminProductSectionActionGroup" stepKey="expandImageAndVideosSection"> + <argument name="sectionSelector" value="{{AdminProductImagesSection.productImagesToggle}}"/> + <argument name="sectionDependentSelector" value="{{AdminProductImagesSection.imageUploadButton}}"/> + </actionGroup> + <dontSeeElementInDOM selector="{{AdminProductImagesSection.imageElement}}" stepKey="dontSeeProductImage"/> + + <!-- Admin: Verify Configurable Product on Product Index Page --> + <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertConfigurableProductInAdminGrid"> + <argument name="product" value="ImportConfigurable"/> + </actionGroup> + <seeNumberOfElements selector="{{AdminProductGridSection.productGridRows}}" userInput="1" stepKey="seeOnly1Product4"/> + + <!-- Admin: Verify Configurable Product on Edit Product Page --> + <actionGroup ref="AssertProductInfoOnEditPageActionGroup" stepKey="assertConfigurableProductOnEditPage"> + <argument name="product" value="ImportConfigurable"/> + </actionGroup> + <actionGroup ref="ExpandAdminProductSectionActionGroup" stepKey="expandImageAndVideosSection2"> + <argument name="sectionSelector" value="{{AdminProductImagesSection.productImagesToggle}}"/> + <argument name="sectionDependentSelector" value="{{AdminProductImagesSection.imageUploadButton}}"/> + </actionGroup> + <dontSeeElementInDOM selector="{{AdminProductImagesSection.imageElement}}" stepKey="dontSeeProductImage2"/> + + <!-- Storefront: Verify Configurable Product In Category --> + <actionGroup ref="StorefrontNavigateToCategoryUrlActionGroup" stepKey="goToCategoryPage"> + <argument name="categoryUrl" value="{{Import1.name_lwr}}"/> + </actionGroup> + <seeNumberOfElements selector="{{StorefrontCategoryMainSection.productName}}" userInput="1" stepKey="seeOnly1Product5"/> + <see selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{ImportConfigurable.name}}" stepKey="seeConfigurableProduct"/> + <dontSee selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{ImportSimple1.name}}" stepKey="dontSeeSimpleProduct1"/> + <dontSee selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{ImportSimple2.name}}" stepKey="dontSeeSimpleProduct2"/> + <dontSee selector="{{StorefrontCategoryMainSection.productName}}" userInput="{{ImportSimple3.name}}" stepKey="dontSeeSimpleProduct3"/> + + <!-- Storefront: Verify Configurable Product Info & Image --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductStorefrontPage"> + <argument name="productUrl" value="{{ImportConfigurable.urlKey}}"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{ImportConfigurable.name}}" stepKey="seeProductName"/> + <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{ImportConfigurable.sku}}" stepKey="seeSku"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="As low as ${{ImportSimple3.price}}" stepKey="seePrice"/> + <seeElement selector="{{StorefrontProductInfoMainSection.productImageSrc('placeholder')}}" stepKey="seePlaceholderImage"/> + + <!-- Storefront: Verify Configurable Product Option 1 Info & Image --> + <actionGroup ref="StorefrontProductPageSelectDropDownOptionValueActionGroup" stepKey="selectOption1"> + <argument name="attributeLabel" value="{{ProductAttributeFrontendLabelImport1.label}}"/> + <argument name="optionLabel" value="{{ProductAttributeOptionOneForExportImport.label}}"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{ImportConfigurable.name}}" stepKey="seeProductName2"/> + <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{ImportConfigurable.sku}}" stepKey="seeSku2"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="${{ImportSimple1.price}}" stepKey="seePrice2"/> + <seeElement selector="{{StorefrontProductInfoMainSection.productImageSrc(MagentoLogo.filename)}}" stepKey="seeImage1"/> + + <!-- Storefront: Verify Configurable Product Option 2 Info & Image --> + <actionGroup ref="StorefrontProductPageSelectDropDownOptionValueActionGroup" stepKey="selectOption2"> + <argument name="attributeLabel" value="{{ProductAttributeFrontendLabelImport1.label}}"/> + <argument name="optionLabel" value="{{ProductAttributeOptionTwoForExportImport.label}}"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{ImportConfigurable.name}}" stepKey="seeProductName3"/> + <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{ImportConfigurable.sku}}" stepKey="seeSku3"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="${{ImportSimple2.price}}" stepKey="seePrice3"/> + <seeElement selector="{{StorefrontProductInfoMainSection.productImageSrc(TestImage.filename)}}" stepKey="seeImage2"/> + + <!-- Storefront: Verify Configurable Product Option 3 Info & Image --> + <actionGroup ref="StorefrontProductPageSelectDropDownOptionValueActionGroup" stepKey="selectOption3"> + <argument name="attributeLabel" value="{{ProductAttributeFrontendLabelImport1.label}}"/> + <argument name="optionLabel" value="{{ProductAttributeOptionThreeForImport.label}}"/> + </actionGroup> + <see selector="{{StorefrontProductInfoMainSection.productName}}" userInput="{{ImportConfigurable.name}}" stepKey="seeProductName4"/> + <see selector="{{StorefrontProductInfoMainSection.productSku}}" userInput="{{ImportConfigurable.sku}}" stepKey="seeSku4"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="${{ImportSimple3.price}}" stepKey="seePrice4"/> + <seeElement selector="{{StorefrontProductInfoMainSection.productImageSrc('placeholder')}}" stepKey="seePlaceholderImage2"/> + </test> +</tests> From 476e755752d7348f303b316990b51937568dcd90 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 13 Jan 2021 13:40:52 -0600 Subject: [PATCH 198/242] B2B-1640: Add MFTF test for MC-38222 - Adding MFTF S3 import test for MC-38222 --- ...igurableProductsWithAssignedImagesTest.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml diff --git a/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml new file mode 100644 index 0000000000000..b8d9f57dc4d2c --- /dev/null +++ b/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -0,0 +1,34 @@ +<?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="AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest" extends="AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest"> + <annotations> + <features value="AwsS3"/> + <stories value="Import Products"/> + <title value="Import Configurable Product With Simple Child Products With Images"/> + <description value="Imports a .csv file containing a configurable product with 3 child simple products that + have images. Verifies that products are imported successfully and that the images are attached to the + products as expected."/> + <severity value="MAJOR"/> + <group value="importExport"/> + <group value="remote_storage_aws_s3"/> + </annotations> + + <before> + <!-- Enable AWS S3 Remote Storage --> + <magentoCLI command="setup:config:set {{RemoteStorageAwsS3ConfigData.enable_options}}" stepKey="enableRemoteStorage"/> + </before> + + <after> + <!-- Disable AWS S3 Remote Storage --> + <magentoCLI command="setup:config:set {{RemoteStorageAwsS3ConfigData.disable_options}}" stepKey="disableRemoteStorage"/> + </after> + </test> +</tests> From b850e35ff8e97789e725e121ff5d9890375d969c Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 13 Jan 2021 13:55:05 -0600 Subject: [PATCH 199/242] B2B-1640: Add MFTF test for MC-38222 - Adding csv file for import --- .../tests/_data/configurable_and_simple_child_products.csv | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv diff --git a/dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv b/dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv new file mode 100644 index 0000000000000..6eaf2a2429a74 --- /dev/null +++ b/dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv @@ -0,0 +1,5 @@ +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,giftcard_type,giftcard_allow_open_amount,giftcard_open_amount_min,giftcard_open_amount_max,giftcard_amount,use_config_is_redeemable,giftcard_is_redeemable,use_config_lifetime,giftcard_lifetime,use_config_allow_message,giftcard_allow_message,use_config_email_template,giftcard_email_template,associated_skus,downloadable_links,downloadable_samples,configurable_variations,configurable_variation_labels +import-simple1,,Default,simple,Default Category/Import1,base,import-simple1,,,12,1,Taxable Goods,Not Visible Individually,12,,,,import-simple1,Conf11,Conf11,Conf11 ,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option1,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/m/a/magento-logo.png,Magento Logo,,,,,,,,,,,,,,,,,,,,,,,,,, +import-simple2,,Default,simple,Default Category/Import1,base,import-simple2,,,12,1,Taxable Goods,Not Visible Individually,15,,,,import-simple2,Conf11,Conf11,Conf11 ,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option2,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/t/e/test_image.jpg,Test Image,,,,,,,,,,,,,,,,,,,,,,,,,, +import-simple3,,Default,simple,Default Category/Import1,base,import-simple3,,,12,1,Taxable Goods,Not Visible Individually,10,,,,import-simple3,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option3,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +import-configurable,,Default,configurable,Default Category/Import1,base,import-configurable,,,12,1,Taxable Goods,"Catalog, Search",,,,,import-configurable,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,Use config,,,,,,,Use config,,gift_wrapping_available=Use config,0,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,",,",,,,,,,,,,,,,,,,,,,,,,,,,"sku=import-simple1,import_attribute1=option1|sku=import-simple2,import_attribute1=option2|sku=import-simple3,import_attribute1=option3",import_attribute1=import_attribute1 \ No newline at end of file From 8d203cccaebf0a4dd4c2b6a2fc11a3559d9c693d Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Wed, 13 Jan 2021 20:24:16 -0600 Subject: [PATCH 200/242] B2B-1640: Add MFTF test for MC-38222 - Skipping S3 test --- ...rtSimpleAndConfigurableProductsWithAssignedImagesTest.xml | 5 ++++- ...rtSimpleAndConfigurableProductsWithAssignedImagesTest.xml | 2 +- ...le_child_products.csv => import_configurable_product.csv} | 0 3 files changed, 5 insertions(+), 2 deletions(-) rename dev/tests/acceptance/tests/_data/{configurable_and_simple_child_products.csv => import_configurable_product.csv} (100%) diff --git a/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index b8d9f57dc4d2c..fe8c6c6f7f9ef 100644 --- a/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/AwsS3/Test/Mftf/Test/AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -12,13 +12,16 @@ <annotations> <features value="AwsS3"/> <stories value="Import Products"/> - <title value="Import Configurable Product With Simple Child Products With Images"/> + <title value="S3 - Import Configurable Product With Simple Child Products With Images"/> <description value="Imports a .csv file containing a configurable product with 3 child simple products that have images. Verifies that products are imported successfully and that the images are attached to the products as expected."/> <severity value="MAJOR"/> <group value="importExport"/> <group value="remote_storage_aws_s3"/> + <skip> + <issueId value="MC-39280"/> + </skip> </annotations> <before> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index 8d19407d05c55..93fe8206d69b7 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -71,7 +71,7 @@ <!-- Import Configurable Product with Simple Child Products & Assert No Errors --> <actionGroup ref="AdminNavigateToImportPageActionGroup" stepKey="navigateToImportPage"/> <actionGroup ref="AdminFillImportFormActionGroup" stepKey="fillImportForm"> - <argument name="importFile" value="configurable_and_simple_child_products.csv"/> + <argument name="importFile" value="import_configurable_product.csv"/> </actionGroup> <actionGroup ref="AdminClickCheckDataImportActionGroup" stepKey="clickCheckData"/> <see selector="{{AdminImportValidationMessagesSection.success}}" userInput="File is valid! To start import process press "Import" button" stepKey="seeCheckDataResultMessage"/> diff --git a/dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv b/dev/tests/acceptance/tests/_data/import_configurable_product.csv similarity index 100% rename from dev/tests/acceptance/tests/_data/configurable_and_simple_child_products.csv rename to dev/tests/acceptance/tests/_data/import_configurable_product.csv From 9366f356a81c526ca1c144936aa7d9cb8856a2f0 Mon Sep 17 00:00:00 2001 From: Anna Pak <a.pak@atwix.com> Date: Thu, 14 Jan 2021 09:06:57 +0200 Subject: [PATCH 201/242] added missed stepKeys --- .../Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml | 2 ++ ...ductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml | 2 ++ ...leProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml | 2 ++ ...pleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml | 2 ++ ...impleProductWithRegularPriceInStockWithCustomOptionsTest.xml | 2 ++ .../AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml | 2 ++ 6 files changed, 12 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml index c82bcc519ef80..45a5f8592b0e9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductTieredPriceTest.xml @@ -144,6 +144,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductTierPrice300InStock.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductTierPrice300InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml index 50fe488e0c57c..3d7af3c330564 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogAndSearchTest.xml @@ -124,6 +124,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductRegularPrice245InStock.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice245InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml index 7faeba9bceb4f..0e83ea4655483 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInCatalogOnlyTest.xml @@ -124,6 +124,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductRegularPrice32501InStock.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32501InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml index 2ca367d72383c..1af8ff3265047 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockVisibleInSearchOnlyTest.xml @@ -122,6 +122,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductRegularPrice325InStock.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice325InStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml index 154f60151ab5f..6066a02110f13 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceInStockWithCustomOptionsTest.xml @@ -142,6 +142,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductRegularPriceCustomOptions.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer see customizable options are Required --> <seeElement selector="{{StorefrontProductInfoMainSection.requiredCustomSelect(simpleProductCustomizableOption.title)}}" stepKey="verifyFirstCustomOptionIsRequired"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml index 7b89492cbb574..881105ad2ddae 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateSimpleProductWithRegularPriceOutOfStockTest.xml @@ -121,6 +121,8 @@ <actionGroup ref="AssertStorefrontProductStockStatusOnProductPageActionGroup" stepKey="assertStockAvailableOnProductPage"> <argument name="productStockStatus" value="{{simpleProductRegularPrice32503OutOfStock.storefrontStatus}}"/> </actionGroup> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="productPriceAmount"/> + <comment userInput="Comment is added to preserve the step key for backward compatibilityr" stepKey="assertOldPriceTextOnProductPage"/> <!--Verify customer don't see updated simple product link on magento storefront page and is searchable by sku --> <amOnPage url="{{StorefrontProductPage.url(simpleProductRegularPrice32503OutOfStock.urlKey)}}" stepKey="goToMagentoStorefrontPage"/> From bd3c0363b7c01271c8225b98d203de27576a2858 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Thu, 14 Jan 2021 09:47:50 +0200 Subject: [PATCH 202/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- .../AssertNextButtonHiddenProductVideoActionGroup.xml | 1 - .../AssertPrevButtonHiddenProductVideoActionGroup.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml index d6d756847e0b7..6778ade18b496 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml @@ -14,7 +14,6 @@ <description>Validates that the next button is absent on the Storefront Product page.</description> </annotations> - <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml index b5b9e801d3a9c..1a588f4a23f84 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml @@ -14,7 +14,6 @@ <description>Validates that the previous button is absent on the Storefront Product page.</description> </annotations> - <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> </actionGroup> </actionGroups> From 8ff8dbe7e35c3549fc55e4673b093364bb2cf4f7 Mon Sep 17 00:00:00 2001 From: rostyslav-hymon <rostyslav.hymon@transoftgroup.com> Date: Thu, 14 Jan 2021 12:04:53 +0200 Subject: [PATCH 203/242] MC-40379: [Magento Cloud] - [vodacom]-Upsell,Cross Sell Products are visible in Graphql Response even those the product is disabled --- .../Products/DataProvider/Product.php | 2 +- .../RelatedProduct/GetRelatedProductsTest.php | 36 ++++++++++ .../products_related_disabled_in_store.php | 70 +++++++++++++++++++ ...cts_related_disabled_in_store_rollback.php | 33 +++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store_rollback.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php index 3e955ae303453..30be41072242b 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php @@ -89,7 +89,7 @@ public function getList( $this->collectionPreProcessor->process($collection, $searchCriteria, $attributes, $context); - if (!$isChildSearch) { + if ($isChildSearch) { $visibilityIds = $isSearch ? $this->visibility->getVisibleInSearchIds() : $this->visibility->getVisibleInCatalogIds(); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php index f2cf90c95de18..8575f1d33c435 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php @@ -190,4 +190,40 @@ private function assertRelatedProducts(array $relatedProducts): void self::assertEquals($product['url_key'], $productExpectedData['url_key']); } } + + /** + * Test query with disabled linked product in the default store + * + * @magentoApiDataFixture Magento/Catalog/_files/products_related_disabled_in_store.php + * + * @return void + */ + public function testQueryDisableRelatedProductInStore(): void + { + $productSku = 'simple_with_related'; + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + related_products + { + sku + name + url_key + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query, [], '', ['Store' => 'default']); + + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + self::assertArrayHasKey(0, $response['products']['items']); + self::assertArrayHasKey('related_products', $response['products']['items'][0]); + $relatedProducts = $response['products']['items'][0]['related_products']; + self::assertCount(0, $relatedProducts); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store.php new file mode 100644 index 0000000000000..b8e6d4702b44f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Eav\Model\Config; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Catalog\Api\Data\ProductLinkInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsite = $websiteRepository->get('base'); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$defaultAttributeSet = $objectManager->get(Config::class)->getEntityType(Product::ENTITY)->getDefaultAttributeSetId(); +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +/** @var ProductInterfaceFactory $productInterfaceFactory */ +$productInterfaceFactory = $objectManager->get(ProductInterfaceFactory::class); + +/** @var Product $product */ +$product = $productInterfaceFactory->create(); +$product->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId($defaultAttributeSet) + ->setStoreId($storeManager->getDefaultStoreView()->getId()) + ->setWebsiteIds([$baseWebsite->getId()]) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + ->setWeight(18) + ->setStockData(['use_config_manage_stock' => 0]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); + +$simple = $productRepository->save($product); +$simple->setStoreId($storeManager->getDefaultStoreView()->getId()) +->setStatus(Status::STATUS_DISABLED); +$productRepository->save($simple); +/** @var ProductLinkInterface $productLink */ +$productLink = $objectManager->create(ProductLinkInterface::class); +$productLink->setSku('simple_with_related'); +$productLink->setLinkedProductSku('simple'); +$productLink->setPosition(1); +$productLink->setLinkType('related'); + +/** @var Product $product */ +$product = $productInterfaceFactory->create(); +$product->setTypeId(Type::TYPE_SIMPLE) + ->setAttributeSetId($defaultAttributeSet) + ->setStoreId($storeManager->getDefaultStoreView()->getId()) + ->setWebsiteIds([$baseWebsite->getId()]) + ->setName('Simple Product With Related Product') + ->setSku('simple_with_related') + ->setPrice(10) + ->setWeight(18) + ->setProductLinks([$productLink]) + ->setStockData(['use_config_manage_stock' => 0]) + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED); + +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store_rollback.php new file mode 100644 index 0000000000000..6ca27b71b9057 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_related_disabled_in_store_rollback.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); + +try { + $firstProduct = $productRepository->get('simple', false, null, true); + $productRepository->delete($firstProduct); +} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { + //Product already removed +} + +try { + $secondProduct = $productRepository->get('simple_with_related', false, null, true); + $productRepository->delete($secondProduct); +} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { + //Product already removed +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From c6fd2f9a6f7db39ca22ad26ae4a765782bb758bb Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Thu, 14 Jan 2021 13:03:16 +0200 Subject: [PATCH 204/242] MC-40136: Create automated test for: "Update items stock status and low stock date after save config" --- .../_files/product_simple_backorders_no.php | 8 ++++---- .../Model/ResourceModel/Stock/ItemTest.php | 17 ++++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php index 34bf9239fbe90..3d2be62981fc2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_backorders_no.php @@ -5,21 +5,21 @@ */ declare(strict_types=1); +use Magento\Catalog\Api\Data\ProductInterfaceFactory; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Helper\DefaultCategory; use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Catalog\Model\Product\Type; use Magento\Catalog\Model\Product\Visibility; -use Magento\Catalog\Model\ProductFactory; use Magento\CatalogInventory\Model\Stock; use Magento\Store\Api\WebsiteRepositoryInterface; use Magento\TestFramework\Helper\Bootstrap; $objectManager = Bootstrap::getObjectManager(); -/** @var ProductRepositoryInterface $productRepositoryFactory */ +/** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); -/** @var ProductFactory $productFactory */ -$productFactory = $objectManager->get(ProductFactory::class); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); /** @var WebsiteRepositoryInterface $websiteRepository */ $websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); /** @var DefaultCategory $defaultCategory */ diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php index e003c2cbbc9a5..587d050f5c7e6 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Stock/ItemTest.php @@ -11,6 +11,7 @@ use Magento\Catalog\Model\Indexer\Product\Price\Processor as PriceProcessor; use Magento\CatalogInventory\Model\Configuration; use Magento\CatalogInventory\Model\Indexer\Stock\Processor as StockProcessor; +use Magento\CatalogInventory\Model\ResourceModel\Stock\Item as ItemResource; use Magento\CatalogInventory\Model\Stock; use Magento\CatalogInventory\Model\StockRegistryStorage; use Magento\Framework\App\Config\MutableScopeConfigInterface; @@ -34,7 +35,7 @@ class ItemTest extends TestCase /** @var MutableScopeConfigInterface */ private $mutableConfig; - /** @var Item */ + /** @var ItemResource */ private $stockItemResource; /** @var StoreManagerInterface */ @@ -57,9 +58,11 @@ class ItemTest extends TestCase */ protected function setUp(): void { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); $this->mutableConfig = $this->objectManager->get(MutableScopeConfigInterface::class); - $this->stockItemResource = $this->objectManager->get(Item::class); + $this->stockItemResource = $this->objectManager->get(ItemResource::class); $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); $this->productRepository->cleanCache(); @@ -72,11 +75,11 @@ protected function setUp(): void * @dataProvider updateSetOutOfStockDataProvider * @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php * @magentoDataFixture Magento/Catalog/_files/product_simple_backorders_no.php - * @magentoConfigFixture default_store cataloginventory/item_options/min_qty 105 - * @magentoConfigFixture default_store cataloginventory/item_options/manage_stock 1 + * @magentoConfigFixture current_store cataloginventory/item_options/min_qty 105 + * @magentoConfigFixture current_store cataloginventory/item_options/manage_stock 1 + * @magentoDbIsolation disabled * @param int $backorders * @param array $expectedStockItems - * @magentoDbIsolation disabled * @return void */ public function testUpdateSetOutOfStock(int $backorders, array $expectedStockItems): void @@ -131,10 +134,10 @@ public function updateSetOutOfStockDataProvider(): array * @dataProvider updateUpdateSetInStockDataProvider * @magentoDataFixture Magento/Catalog/_files/out_of_stock_product_with_category.php * @magentoDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php - * @magentoConfigFixture default_store cataloginventory/item_options/min_qty 50 + * @magentoConfigFixture current_store cataloginventory/item_options/min_qty 50 + * @magentoDbIsolation disabled * @param int $manageStock * @param array $expectedStockItems - * @magentoDbIsolation disabled * @return void */ public function testUpdateSetInStock(int $manageStock, array $expectedStockItems): void From a690b16a7fab4753301f4c6bd9468d53bc7a44a7 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Thu, 14 Jan 2021 14:28:20 +0200 Subject: [PATCH 205/242] MC-36149: [CLOUD] 'Be the first to review this product' link is not changed after admin has approved the review --- ...endSummaryDataToObjectByEntityCodeTest.php | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php diff --git a/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php b/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php new file mode 100644 index 0000000000000..e42ca82945d5e --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Review\Test\Unit\Model; + +use Magento\Catalog\Model\Product; +use Magento\Framework\DB\Select; +use Magento\Review\Model\AppendSummaryDataToObjectByEntityCode; +use Magento\Review\Model\ResourceModel\Review\Summary as ResourceSummary; +use Magento\Review\Model\ResourceModel\Review\Summary\Collection as SummaryCollection; +use Magento\Review\Model\ResourceModel\Review\Summary\CollectionFactory as SummaryCollectionFactory; +use Magento\Review\Model\Review\Summary; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Unit tests for \Magento\Review\Model\AppendSummaryDataToObjectByEntityCode class + */ +class AppendSummaryDataToObjectByEntityCodeTest extends TestCase +{ + /** + * @var SummaryCollectionFactory|MockObject + */ + private $summaryCollectionFactoryMock; + + /** + * @var Product|MockObject + */ + private $productMock; + + /** + * @var Summary|MockObject + */ + private $summaryMock; + + /** + * @var SummaryCollection|MockObject + */ + private $summaryCollectionMock; + + /** + * @var Select|MockObject + */ + private $selectMock; + + /** + * @var ResourceSummary|MockObject + */ + private $resourceSummaryMock; + + /** + * @var AppendSummaryDataToObjectByEntityCode + */ + private $model; + + /** + * @inheriDoc + */ + protected function setUp(): void + { + $this->summaryCollectionFactoryMock = $this->getMockBuilder(SummaryCollectionFactory::class) + ->disableOriginalConstructor() + ->onlyMethods(['create']) + ->getMock(); + + $this->productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->onlyMethods(['getId', 'addData']) + ->getMock(); + + $this->summaryMock = $this->getMockBuilder(Summary::class) + ->disableOriginalConstructor() + ->onlyMethods(['getData']) + ->getMock(); + + $this->summaryCollectionMock = $this->getMockBuilder(SummaryCollection::class) + ->disableOriginalConstructor() + ->onlyMethods( + [ + 'addStoreFilter', + 'getSelect', + 'getResource', + 'getFirstItem', + ] + ) + ->getMock(); + + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->onlyMethods(['joinLeft', 'where']) + ->getMock(); + + $this->resourceSummaryMock = $this->getMockBuilder(ResourceSummary::class) + ->disableOriginalConstructor() + ->onlyMethods(['getTable']) + ->getMock(); + + $this->model = new AppendSummaryDataToObjectByEntityCode( + $this->summaryCollectionFactoryMock + ); + } + + /** + * @return void + */ + public function testExecute(): void + { + $productId = 6; + $storeId = 4; + $entityCode = 'product'; + $summaryData = [ + 'reviews_count' => 2, + 'rating_summary' => 80, + ]; + + $this->productMock->expects($this->once()) + ->method('getId') + ->willReturn($productId); + + $this->productMock->expects($this->once()) + ->method('addData') + ->with($summaryData) + ->willReturnSelf(); + + $this->summaryMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap( + [ + ['reviews_count', null, $summaryData['reviews_count']], + ['rating_summary', null, $summaryData['rating_summary']], + ] + ); + + $this->summaryCollectionMock->expects($this->once()) + ->method('addStoreFilter') + ->with($storeId) + ->willReturnSelf(); + $this->summaryCollectionMock->expects($this->once()) + ->method('getSelect') + ->willReturn($this->selectMock); + $this->summaryCollectionMock->expects($this->once()) + ->method('getResource') + ->willReturn($this->resourceSummaryMock); + + $this->resourceSummaryMock->expects($this->once()) + ->method('getTable') + ->willReturn('table_name'); + + $this->summaryCollectionMock->expects($this->once()) + ->method('getFirstItem') + ->willReturn($this->summaryMock); + + $this->selectMock->expects($this->once()) + ->method('joinLeft') + ->willReturnSelf(); + $this->selectMock->expects($this->exactly(2)) + ->method('where') + ->willReturnSelf(); + + $this->summaryCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->summaryCollectionMock); + + $this->model->execute($this->productMock, $storeId, $entityCode); + } +} From ef975c5d883dc5ff05a1a5c825773dcae7b06284 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 14 Jan 2021 14:57:14 +0200 Subject: [PATCH 206/242] MC-40053: Create automated test for: "Update attribute option by API call" --- ...AttributeOptionManagementInterfaceTest.php | 122 +++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php index 39ca42b57511e..d1cc52fc52e48 100644 --- a/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -25,6 +25,7 @@ class ProductAttributeOptionManagementInterfaceTest extends WebapiAbstract { private const ATTRIBUTE_CODE = 'select_attribute'; + private const SERVICE_NAME_UPDATE = 'catalogProductAttributeOptionUpdateV1'; private const SERVICE_NAME = 'catalogProductAttributeOptionManagementV1'; private const SERVICE_VERSION = 'V1'; private const RESOURCE_PATH = '/V1/products/attributes'; @@ -47,7 +48,8 @@ public function testAdd( int $expectedSwatchType, string $expectedLabel, string $expectedValue - ) { + ) + { $objectManager = Bootstrap::getObjectManager(); /** @var $attributeRepository AttributeRepository */ $attributeRepository = $objectManager->get(AttributeRepository::class); @@ -74,7 +76,7 @@ public function testAdd( ); $this->assertNotNull($response); - $optionId = (int) ltrim($response, 'id_'); + $optionId = (int)ltrim($response, 'id_'); $swatch = $this->getSwatch($optionId); $this->assertEquals($expectedValue, $swatch->getValue()); $this->assertEquals($expectedSwatchType, $swatch->getType()); @@ -83,6 +85,41 @@ public function testAdd( $this->assertEquals($expectedLabel, $options[2]->getLabel()); } + /** + * @magentoApiDataFixture Magento/Swatches/_files/text_swatch_attribute.php + */ + public function testUpdate() + { + $testAttributeCode = 'test_configurable'; + $optionData = [ + AttributeOptionInterface::LABEL => 'Fixture Option Changed', + AttributeOptionInterface::VALUE => 'option_value', + ]; + + $existOptionLabel = 'option 1'; + $existAttributeOption = $this->getAttributeOption($testAttributeCode, $existOptionLabel); + $optionId = $existAttributeOption['value']; + + $response = $this->webApiCallAttributeOptions( + $testAttributeCode, + Request::HTTP_METHOD_PUT, + 'update', + [ + 'attributeCode' => $testAttributeCode, + 'optionId' => $optionId, + 'option' => $optionData, + ], + $optionId + ); + $this->assertTrue($response); + $this->assertNotNull( + $this->getAttributeOption( + $testAttributeCode, + $optionData[AttributeOptionLabelInterface::LABEL] + ) + ); + } + /** * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -222,4 +259,85 @@ private function getSwatch(int $optionId) $collection->setPageSize(1); return $collection->getFirstItem(); } + + /** + * Perform Web API call to the system under test + * + * @param string $attributeCode + * @param string $httpMethod + * @param string $soapMethod + * @param array $arguments + * @param null $storeCode + * @param null $optionId + * @return array|bool|float|int|string + */ + private function webApiCallAttributeOptions( + string $attributeCode, + string $httpMethod, + string $soapMethod, + array $arguments = [], + $optionId = null, + $storeCode = null + ) { + $resourcePath = self::RESOURCE_PATH . "/{$attributeCode}/options"; + if ($optionId) { + $resourcePath .= '/' . $optionId; + } + $serviceName = $soapMethod === 'update' ? self::SERVICE_NAME_UPDATE : self::SERVICE_NAME; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => $resourcePath, + 'httpMethod' => $httpMethod, + ], + 'soap' => [ + 'service' => $serviceName, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => $serviceName . $soapMethod, + ], + ]; + + return $this->_webApiCall($serviceInfo, $arguments, null, $storeCode); + } + + /** + * @param string $testAttributeCode + * @param string|null $storeCode + * @return array|bool|float|int|string + */ + private function getAttributeOptions(string $testAttributeCode, ?string $storeCode = null) + { + return $this->webApiCallAttributeOptions( + $testAttributeCode, + Request::HTTP_METHOD_GET, + 'getItems', + ['attributeCode' => $testAttributeCode], + null, + $storeCode + ); + } + + /** + * @param string $attributeCode + * @param string $optionLabel + * @param string|null $storeCode + * @return array|null + */ + private function getAttributeOption( + string $attributeCode, + string $optionLabel, + ?string $storeCode = null + ): ?array + { + $attributeOptions = $this->getAttributeOptions($attributeCode, $storeCode); + $option = null; + /** @var array $attributeOption */ + foreach ($attributeOptions as $attributeOption) { + if ($attributeOption['label'] === $optionLabel) { + $option = $attributeOption; + break; + } + } + + return $option; + } } From b208c0b31acdd776c4d576778be2499b617c2260 Mon Sep 17 00:00:00 2001 From: rostyslav-hymon <rostyslav.hymon@transoftgroup.com> Date: Thu, 14 Jan 2021 14:59:41 +0200 Subject: [PATCH 207/242] MC-40379: [Magento Cloud] - [vodacom]-Upsell,Cross Sell Products are visible in Graphql Response even those the product is disabled --- .../Model/Resolver/Products/DataProvider/Deferred/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Deferred/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Deferred/Product.php index 22bbc991a78e2..8218c22b8056d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Deferred/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Deferred/Product.php @@ -132,7 +132,7 @@ private function fetch() : array $this->searchCriteriaBuilder->create(), $this->attributeCodes, false, - true + false ); /** @var \Magento\Catalog\Model\Product $product */ From 4099fef3d1981815d5b976c5c07411e36e200dee Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 14 Jan 2021 08:15:18 -0600 Subject: [PATCH 208/242] B2B-1640: Add MFTF test for MC-38222 - Adding reindex to test --- ...tSimpleAndConfigurableProductsWithAssignedImagesTest.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index 93fe8206d69b7..bc496a06e52cb 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -81,6 +81,12 @@ <see selector="{{AdminImportValidationMessagesSection.messageByType('success')}}" userInput="Import successfully done" stepKey="seeImportMessage"/> <dontSeeElementInDOM selector="{{AdminImportValidationMessagesSection.importErrorList}}" stepKey="dontSeeErrorMessage2"/> + <!-- Reindex --> + <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> + <argument name="indices" value=""/> + </actionGroup> + <pause stepKey="pause"/> + <!-- Admin: Verify Simple Product 1 on Product Index Page --> <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct1InAdminGrid"> <argument name="product" value="ImportSimple1"/> From 02163a683dbe5602c2a04fcdb8628ec5240e01ea Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 14 Jan 2021 08:16:11 -0600 Subject: [PATCH 209/242] B2B-1640: Add MFTF test for MC-38222 - Remove pause --- ...ImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index bc496a06e52cb..df7c671d6a5b6 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -85,7 +85,6 @@ <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> </actionGroup> - <pause stepKey="pause"/> <!-- Admin: Verify Simple Product 1 on Product Index Page --> <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct1InAdminGrid"> From 942e44e09bf682bb1fc4ef04d144c44425a56104 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Thu, 14 Jan 2021 17:32:10 +0200 Subject: [PATCH 210/242] MC-35640: The product is not added to the cart --- .../Msrp/Test/Mftf/Data/MsrpSettingsData.xml | 7 ++ .../Msrp/Test/Mftf/Data/ProductData.xml | 4 ++ .../Test/Mftf/Metadata/MsrpSettingsMeta.xml | 5 +- .../Section/StorefrontMsrpCategorySection.xml | 14 ++++ .../Mftf/Section/StorefrontMsrpSection.xml | 13 ++++ ...oductToCartFromPopupOnCategoryPageTest.xml | 65 +++++++++++++++++++ .../base/templates/product/price/msrp.phtml | 9 +-- 7 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml create mode 100644 app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml create mode 100644 app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml diff --git a/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml index 3922bb4868914..941f4acbcc4e4 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Data/MsrpSettingsData.xml @@ -21,4 +21,11 @@ <entity name="DisableMAP" type="msrp_settings_config"> <data key="value">0</data> </entity> + + <entity name="MsrpDisplayPriceOnGesture" type="msrp_settings_config"> + <requiredEntity type="display_price_type">DisplayPriceOnGesture</requiredEntity> + </entity> + <entity name="DisplayPriceOnGesture" type="msrp_settings_config"> + <data key="value">1</data> + </entity> </entities> diff --git a/app/code/Magento/Msrp/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Msrp/Test/Mftf/Data/ProductData.xml index aa79b6032df4b..af66d64c6b11c 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Data/ProductData.xml @@ -13,4 +13,8 @@ <requiredEntity type="custom_attribute_array">ApiProductCost</requiredEntity> <requiredEntity type="custom_attribute_array">ApiProductMsrp</requiredEntity> </entity> + <entity name="SimpleProductWithMsrp" type="product" extends="SimpleProduct"> + <data key="price">100.00</data> + <requiredEntity type="custom_attribute_array">ApiProductMsrp</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Msrp/Test/Mftf/Metadata/MsrpSettingsMeta.xml b/app/code/Magento/Msrp/Test/Mftf/Metadata/MsrpSettingsMeta.xml index be91a548ad909..d12107dc63198 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Metadata/MsrpSettingsMeta.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Metadata/MsrpSettingsMeta.xml @@ -14,8 +14,11 @@ <object key="enabled" dataType="enabled"> <field key="value">string</field> </object> + <object key="display_price_type" dataType="display_price_type"> + <field key="value">string</field> + </object> </object> </object> </object> </operation> -</operations> \ No newline at end of file +</operations> diff --git a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml new file mode 100644 index 0000000000000..2f07d92ee412a --- /dev/null +++ b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.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="StorefrontMsrpCategorySection"> + <element name="clickForPrice" type="button" selector="//a[normalize-space() = '{{productName}}']/following::div[@data-role='priceBox']/a[@class='action map-show-info']" parameterized="true" timeout="30"/> + <element name="mapPrice" type="button" selector="//a[normalize-space() = '{{productName}}']/following::div[@data-role='priceBox']//span[contains(@class, 'price-msrp_price')]" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml new file mode 100644 index 0000000000000..98c4ad7245dc4 --- /dev/null +++ b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontMsrpSection"> + <element name="popupAddToCartButton" type="button" selector="#map-popup-click-for-price .action.tocart" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml new file mode 100644 index 0000000000000..839ddd99786da --- /dev/null +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontAddMapProductToCartFromPopupOnCategoryPageTest"> + <annotations> + <features value="Msrp"/> + <stories value="Minimum advertised price"/> + <title value="Add simple product with MAP to cart from popup on category page"/> + <description value="Check that simple product with MAP is successfully added to cart from popup on category page"/> + <severity value="MAJOR"/> + <testCaseId value="MC-40419"/> + <useCaseId value="MC-35640"/> + <group value="Msrp"/> + </annotations> + <before> + <!-- Enable Minimum advertised Price --> + <createData entity="MsrpEnableMAP" stepKey="enableMAP"/> + + <!-- Display Price in Popup --> + <createData entity="MsrpDisplayPriceOnGesture" stepKey="displayPriceOnGesture"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create product with MAP --> + <createData entity="SimpleProductWithMsrp" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + </before> + <after> + <!-- Delete product and category --> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + + <!-- Disable Minimum advertised Price --> + <createData entity="MsrpDisableMAP" stepKey="disableMAP"/> + </after> + + <!-- Open created category on Storefront --> + <actionGroup ref="StorefrontNavigateCategoryPageActionGroup" stepKey="navigateToCategoryPage"> + <argument name="category" value="$createCategory$"/> + </actionGroup> + + <!-- Grab and verify MAP price --> + <grabTextFrom selector="{{StorefrontMsrpCategorySection.mapPrice($createProduct.name$)}}" stepKey="grabMapPrice"/> + <assertEquals stepKey="assertMapPrice"> + <actualResult type="const">($grabMapPrice)</actualResult> + <expectedResult type="string">${{ApiProductMsrp.value}}</expectedResult> + </assertEquals> + + <!-- Open 'Click for price' popup and click 'Add to Cart' button --> + <click selector="{{StorefrontMsrpCategorySection.clickForPrice($createProduct.name$)}}" stepKey="clickForPrice"/> + <waitForElementVisible selector="{{StorefrontMsrpSection.popupAddToCartButton}}" stepKey="waitForAddToCartButton"/> + <click selector="{{StorefrontMsrpSection.popupAddToCartButton}}" stepKey="clickAddToCartButton"/> + <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $createProduct.name$ to your shopping cart." stepKey="assertSuccessMessage"/> + </test> +</tests> diff --git a/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml b/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml index 4e011df66974c..95d2ced72912b 100644 --- a/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml +++ b/app/code/Magento/Msrp/view/base/templates/product/price/msrp.phtml @@ -80,12 +80,9 @@ $priceElementIdPrefix = $block->getPriceElementIdPrefix() ? $block->getPriceElem $data['addToCartButton'] = '#product_addtocart_form [type=submit]'; } else { $data['addToCartButton'] = sprintf( - 'form:has(input[type="hidden"][name="product"][value="%s"]) button[type="submit"]', - (int) $productId . ',' . - sprintf( - '.block.widget .price-box[data-product-id=%s]+.product-item-actions button.tocart', - (int)$productId - ) + 'form:has(input[type="hidden"][name="product"][value="%1$s"]) button[type="submit"],' . + '.block.widget .price-box[data-product-id="%1$s"]+.product-item-actions button.tocart', + $productId ); } ?> From 9ad6f135a40958d654c70133d3927ad2a9a1f666 Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Thu, 14 Jan 2021 18:08:30 +0200 Subject: [PATCH 211/242] MC-34851: Foreign key error in MySQL 8.0 from MFTF test --- .../Ui/Controller/Adminhtml/Bookmark/Save.php | 4 + .../Adminhtml/Bookmark/SaveTest.php | 114 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Bookmark/Save.php b/app/code/Magento/Ui/Controller/Adminhtml/Bookmark/Save.php index 803495439d65e..b86b8b27a8162 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/Bookmark/Save.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/Bookmark/Save.php @@ -103,6 +103,10 @@ public function __construct( */ public function execute() { + if (!$this->userContext->getUserId()) { + return; + } + $bookmark = $this->bookmarkFactory->create(); $jsonData = $this->_request->getParam('data'); if (!$jsonData) { diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php new file mode 100644 index 0000000000000..addb259a920e0 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Ui\Test\Unit\Controller\Adminhtml\Bookmark; + +use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\Json\DecoderInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Ui\Api\BookmarkManagementInterface; +use Magento\Ui\Api\BookmarkRepositoryInterface; +use Magento\Ui\Api\Data\BookmarkInterfaceFactory; +use Magento\Ui\Controller\Adminhtml\Bookmark\Save; +use Magento\Backend\App\Action\Context; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * Save controller test. + */ +class SaveTest extends TestCase +{ + /** + * @var MockObject|Context + */ + private $context; + + /** + * @var MockObject|UiComponentFactory + */ + private $factory; + + /** + * @var MockObject|BookmarkRepositoryInterface + */ + private $bookmarkRepository; + + /** + * @var MockObject|BookmarkManagementInterface + */ + private $bookmarkManagement; + + /** + * @var MockObject|BookmarkInterfaceFactory + */ + private $bookmarkFactory; + + /** + * @var MockObject|UserContextInterface + */ + private $userContext; + + /** + * @var MockObject|DecoderInterface + */ + private $jsonDecoder; + + /** + * @var Save + */ + private $unit; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->context = $this->createMock(Context::class); + $this->factory = $this->createMock(UiComponentFactory::class); + $this->bookmarkRepository = $this->createMock(BookmarkRepositoryInterface::class); + $this->bookmarkManagement = $this->createMock(BookmarkManagementInterface::class); + $this->bookmarkFactory = $this->createMock(BookmarkInterfaceFactory::class); + $this->userContext = $this->createMock(UserContextInterface::class); + $this->jsonDecoder = $this->createMock(DecoderInterface::class); + + $this->unit = new Save( + $this->context, + $this->factory, + $this->bookmarkRepository, + $this->bookmarkManagement, + $this->bookmarkFactory, + $this->userContext, + $this->jsonDecoder + ); + } + + /** + * Tests execute method. + * Test when User Context doesn't provide userId. In such a case the method should not be executed. + * + * @return void + */ + public function testExecuteWontBeExecutedWhenNoUserIdInContext(): void + { + $this->factory->expects($this->never()) + ->method($this->anything()); + $this->bookmarkRepository->expects($this->never()) + ->method($this->anything()); + $this->bookmarkManagement->expects($this->never()) + ->method($this->anything()); + $this->bookmarkFactory->expects($this->never()) + ->method($this->anything()); + $this->jsonDecoder->expects($this->never()) + ->method($this->anything()); + + $this->userContext->method('getUserId') + ->willReturn(null); + + $this->unit->execute(); + } +} From 2a8f5a6324fb601abdbe46def6b1d85bbe8f7cb6 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 14 Jan 2021 18:17:32 +0200 Subject: [PATCH 212/242] MC-40053: Create automated test for: "Update attribute option by API call" --- ...AttributeOptionManagementInterfaceTest.php | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php index d1cc52fc52e48..f4eeb12170f4a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Swatches/Api/ProductAttributeOptionManagementInterfaceTest.php @@ -12,6 +12,7 @@ use Magento\Eav\Api\Data\AttributeOptionInterface; use Magento\Eav\Api\Data\AttributeOptionLabelInterface; use Magento\Eav\Model\AttributeRepository; +use Magento\Framework\DataObject; use Magento\Framework\Webapi\Rest\Request; use Magento\Swatches\Model\ResourceModel\Swatch\Collection; use Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory; @@ -33,6 +34,7 @@ class ProductAttributeOptionManagementInterfaceTest extends WebapiAbstract /** * Test add option to swatch attribute * + * @dataProvider addDataProvider * @magentoApiDataFixture Magento/Catalog/Model/Product/Attribute/_files/select_attribute.php * @param array $data * @param array $payload @@ -40,7 +42,7 @@ class ProductAttributeOptionManagementInterfaceTest extends WebapiAbstract * @param string $expectedLabel * @param string $expectedValue * - * @dataProvider addDataProvider + * @return void */ public function testAdd( array $data, @@ -48,8 +50,7 @@ public function testAdd( int $expectedSwatchType, string $expectedLabel, string $expectedValue - ) - { + ): void { $objectManager = Bootstrap::getObjectManager(); /** @var $attributeRepository AttributeRepository */ $attributeRepository = $objectManager->get(AttributeRepository::class); @@ -87,8 +88,9 @@ public function testAdd( /** * @magentoApiDataFixture Magento/Swatches/_files/text_swatch_attribute.php + * @return void */ - public function testUpdate() + public function testUpdate(): void { $testAttributeCode = 'test_configurable'; $optionData = [ @@ -115,7 +117,7 @@ public function testUpdate() $this->assertNotNull( $this->getAttributeOption( $testAttributeCode, - $optionData[AttributeOptionLabelInterface::LABEL] + $optionData[AttributeOptionInterface::LABEL] ) ); } @@ -124,7 +126,7 @@ public function testUpdate() * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function addDataProvider() + public function addDataProvider(): array { return [ 'visual swatch option with value' => [ @@ -249,14 +251,15 @@ public function addDataProvider() * Get swatch model * * @param int $optionId - * @return Swatch + * @return DataObject */ - private function getSwatch(int $optionId) + private function getSwatch(int $optionId): DataObject { /** @var Collection $collection */ $collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)->create(); $collection->addFieldToFilter('option_id', $optionId); $collection->setPageSize(1); + return $collection->getFirstItem(); } @@ -300,6 +303,8 @@ private function webApiCallAttributeOptions( } /** + * Get Attribute options by attribute code + * * @param string $testAttributeCode * @param string|null $storeCode * @return array|bool|float|int|string @@ -317,6 +322,8 @@ private function getAttributeOptions(string $testAttributeCode, ?string $storeCo } /** + * Get Attribute option by attribute code + * * @param string $attributeCode * @param string $optionLabel * @param string|null $storeCode @@ -326,8 +333,7 @@ private function getAttributeOption( string $attributeCode, string $optionLabel, ?string $storeCode = null - ): ?array - { + ): ?array { $attributeOptions = $this->getAttributeOptions($attributeCode, $storeCode); $option = null; /** @var array $attributeOption */ From 00ec932c7ef4bb187e2e7c3556e023ae84ad58dc Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Thu, 14 Jan 2021 18:24:23 +0200 Subject: [PATCH 213/242] MC-34851: Foreign key error in MySQL 8.0 from MFTF test --- .../Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php index addb259a920e0..485c9afdd9ce8 100644 --- a/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php +++ b/app/code/Magento/Ui/Test/Unit/Controller/Adminhtml/Bookmark/SaveTest.php @@ -61,7 +61,7 @@ class SaveTest extends TestCase /** * @var Save */ - private $unit; + private $model; /** * @inheritDoc @@ -76,7 +76,7 @@ protected function setUp(): void $this->userContext = $this->createMock(UserContextInterface::class); $this->jsonDecoder = $this->createMock(DecoderInterface::class); - $this->unit = new Save( + $this->model = new Save( $this->context, $this->factory, $this->bookmarkRepository, @@ -109,6 +109,6 @@ public function testExecuteWontBeExecutedWhenNoUserIdInContext(): void $this->userContext->method('getUserId') ->willReturn(null); - $this->unit->execute(); + $this->model->execute(); } } From 3fef6d1933e6f0eb21446304f5781aa65b0a72c9 Mon Sep 17 00:00:00 2001 From: magento-mts-svc <55515058+magento-mts-svc@users.noreply.github.com> Date: Thu, 14 Jan 2021 12:52:19 -0800 Subject: [PATCH 214/242] [performance] MCP-88: Refactor indexer blocking algorithm (#6513) * MCP-88: Refactor indexer blocking algorithm --- .../Magento/Indexer/Model/Indexer/State.php | 64 ++++++++++- .../Indexer/Model/Mview/View/State.php | 67 +++++++++++- .../Command/IndexerStatusCommandTest.php | 32 +++++- .../Test/Unit/Model/Indexer/StateTest.php | 80 +++++++++++++- .../Test/Unit/Model/Mview/View/StateTest.php | 103 +++++++++++++++--- 5 files changed, 321 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/Indexer/Model/Indexer/State.php b/app/code/Magento/Indexer/Model/Indexer/State.php index ffef44281a024..25fbcb7d15a53 100644 --- a/app/code/Magento/Indexer/Model/Indexer/State.php +++ b/app/code/Magento/Indexer/Model/Indexer/State.php @@ -23,23 +23,59 @@ class State extends \Magento\Framework\Model\AbstractModel implements StateInter */ protected $_eventObject = 'indexer_state'; + /** + * @var \Magento\Framework\Lock\LockManagerInterface + */ + private $lockManager; + + /** + * Prefix for lock mechanism + * + * @var string + */ + private $lockPrefix = 'INDEXER'; + + /** + * DeploymentConfig + * + * @var \Magento\Framework\App\DeploymentConfig + */ + private $configReader; + + /** + * Parameter with path to indexer use_application_lock config + * + * @var string + */ + private $useApplicationLockConfig = 'indexer/use_application_lock'; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Indexer\Model\ResourceModel\Indexer\State $resource * @param \Magento\Indexer\Model\ResourceModel\Indexer\State\Collection $resourceCollection * @param array $data + * @param \Magento\Framework\Lock\LockManagerInterface $lockManager + * @param \Magento\Framework\App\DeploymentConfig $configReader */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Indexer\Model\ResourceModel\Indexer\State $resource, \Magento\Indexer\Model\ResourceModel\Indexer\State\Collection $resourceCollection, - array $data = [] + array $data = [], + \Magento\Framework\Lock\LockManagerInterface $lockManager = null, + \Magento\Framework\App\DeploymentConfig $configReader = null ) { if (!isset($data['status'])) { $data['status'] = self::STATUS_INVALID; } + $this->lockManager = $lockManager ?: \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\Lock\LockManagerInterface::class + ); + $this->configReader = $configReader ?: \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\App\DeploymentConfig::class + ); parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -71,6 +107,15 @@ public function setIndexerId($value) */ public function getStatus() { + if ($this->isUseApplicationLock()) { + if ( + parent::getStatus() == StateInterface::STATUS_WORKING && + !$this->lockManager->isLocked($this->lockPrefix . $this->getIndexerId()) + ) { + return StateInterface::STATUS_INVALID; + } + } + return parent::getStatus(); } @@ -118,6 +163,13 @@ public function loadByIndexer($indexerId) */ public function setStatus($status) { + if ($this->isUseApplicationLock()) { + if ($status == StateInterface::STATUS_WORKING) { + $this->lockManager->lock($this->lockPrefix . $this->getIndexerId()); + } else { + $this->lockManager->unlock($this->lockPrefix . $this->getIndexerId()); + } + } return parent::setStatus($status); } @@ -131,4 +183,14 @@ public function beforeSave() $this->setUpdated(time()); return parent::beforeSave(); } + + /** + * The indexer application locking mechanism is used + * + * @return bool + */ + private function isUseApplicationLock() + { + return $this->configReader->get($this->useApplicationLockConfig) ?: false; + } } diff --git a/app/code/Magento/Indexer/Model/Mview/View/State.php b/app/code/Magento/Indexer/Model/Mview/View/State.php index fe1a3a1e8766d..66cc423f189c7 100644 --- a/app/code/Magento/Indexer/Model/Mview/View/State.php +++ b/app/code/Magento/Indexer/Model/Mview/View/State.php @@ -24,19 +24,49 @@ class State extends \Magento\Framework\Model\AbstractModel implements \Magento\F */ protected $_eventObject = 'mview_state'; + /** + * @var \Magento\Framework\Lock\LockManagerInterface + */ + private $lockManager; + + /** + * Prefix for lock mechanism + * + * @var string + */ + private $lockPrefix = 'MVIEW'; + + /** + * DeploymentConfig + * + * @var \Magento\Framework\App\DeploymentConfig + */ + private $configReader; + + /** + * Parameter with path to indexer use_application_lock config + * + * @var string + */ + private $useApplicationLockConfig = 'indexer/use_application_lock'; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Indexer\Model\ResourceModel\Mview\View\State $resource * @param \Magento\Indexer\Model\ResourceModel\Mview\View\State\Collection $resourceCollection * @param array $data + * @param \Magento\Framework\Lock\LockManagerInterface $lockManager + * @param \Magento\Framework\App\DeploymentConfig $configReader */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Indexer\Model\ResourceModel\Mview\View\State $resource, \Magento\Indexer\Model\ResourceModel\Mview\View\State\Collection $resourceCollection, - array $data = [] + array $data = [], + \Magento\Framework\Lock\LockManagerInterface $lockManager = null, + \Magento\Framework\App\DeploymentConfig $configReader = null ) { if (!isset($data['mode'])) { $data['mode'] = self::MODE_DISABLED; @@ -44,6 +74,12 @@ public function __construct( if (!isset($data['status'])) { $data['status'] = self::STATUS_IDLE; } + $this->lockManager = $lockManager ?: \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\Lock\LockManagerInterface::class + ); + $this->configReader = $configReader ?: \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\App\DeploymentConfig::class + ); parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -112,7 +148,17 @@ public function setMode($mode) */ public function getStatus() { - return $this->getData('status'); + $status = $this->getData('status'); + if ($this->isUseApplicationLock()) { + if ( + $status == \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING && + !$this->lockManager->isLocked($this->lockPrefix . $this->getViewId()) + ) { + return \Magento\Framework\Mview\View\StateInterface::STATUS_IDLE; + } + } + + return $status; } /** @@ -123,6 +169,13 @@ public function getStatus() */ public function setStatus($status) { + if ($this->isUseApplicationLock()) { + if ($status == \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING) { + $this->lockManager->lock($this->lockPrefix . $this->getViewId()); + } else { + $this->lockManager->unlock($this->lockPrefix . $this->getViewId()); + } + } $this->setData('status', $status); return $this; } @@ -170,4 +223,14 @@ public function setVersionId($versionId) $this->setData('version_id', $versionId); return $this; } + + /** + * The indexer application locking mechanism is used + * + * @return bool + */ + private function isUseApplicationLock() + { + return $this->configReader->get($this->useApplicationLockConfig) ?: false; + } } diff --git a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php index 5ad07f914dcbb..35a003ba2f28a 100644 --- a/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Console/Command/IndexerStatusCommandTest.php @@ -41,10 +41,7 @@ private function attachViewToIndexerMock($indexerMock, array $data) ->willReturn(range(0, $data['view']['changelog']['list_size']-1)); /** @var State|MockObject $stateMock */ - $stateMock = $this->getMockBuilder(State::class) - ->disableOriginalConstructor() - ->setMethods(null) - ->getMock(); + $stateMock = $this->getStateMock(); $stateMock->addData($data['view']['state']); @@ -67,6 +64,33 @@ private function attachViewToIndexerMock($indexerMock, array $data) return $indexerMock; } + /** + * @return State + */ + private function getStateMock() + { + $contextMock = $this->createPartialMock(\Magento\Framework\Model\Context::class, ['getEventDispatcher']); + $eventManagerMock = $this->getMockForAbstractClass(\Magento\Framework\Event\ManagerInterface::class); + $contextMock->expects($this->any())->method('getEventDispatcher')->willReturn($eventManagerMock); + $registryMock = $this->createMock(\Magento\Framework\Registry::class); + $resourceMock = $this->createMock(\Magento\Indexer\Model\ResourceModel\Mview\View\State::class); + $resourceCollectionMock = $this->createMock( + \Magento\Indexer\Model\ResourceModel\Mview\View\State\Collection::class + ); + $lockManagerMock = $this->createMock(\Magento\Framework\Lock\LockManagerInterface::class); + $configReaderMock = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); + + return new State( + $contextMock, + $registryMock, + $resourceMock, + $resourceCollectionMock, + [], + $lockManagerMock, + $configReaderMock + ); + } + /** * @param array $indexers * diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/StateTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/StateTest.php index 5c5ab24a75910..31411bcbc96f0 100644 --- a/app/code/Magento/Indexer/Test/Unit/Model/Indexer/StateTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Model/Indexer/StateTest.php @@ -42,6 +42,16 @@ class StateTest extends TestCase */ protected $_resourceCollectionMock; + /** + * @var \Magento\Framework\Lock\LockManagerInterface|MockObject + */ + protected $lockManagerMock; + + /** + * @var \Magento\Framework\App\DeploymentConfig|MockObject + */ + protected $configReaderMock; + protected function setUp(): void { $this->_contextMock = $this->createPartialMock(Context::class, ['getEventDispatcher']); @@ -52,12 +62,17 @@ protected function setUp(): void $this->_resourceCollectionMock = $this->createMock( Collection::class ); + $this->lockManagerMock = $this->createMock(\Magento\Framework\Lock\LockManagerInterface::class); + $this->configReaderMock = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->model = new State( $this->_contextMock, $this->_registryMock, $this->_resourceMock, - $this->_resourceCollectionMock + $this->_resourceCollectionMock, + [], + $this->lockManagerMock, + $this->configReaderMock ); } @@ -82,4 +97,67 @@ public function testSetStatus() $this->model->setStatus($setData); $this->assertEquals($setData, $this->model->getStatus()); } + + public function testSetterAndGetterWithoutApplicationLock() + { + $this->configReaderMock->expects($this->any())->method('get')->willReturn(false); + + $this->lockManagerMock->expects($this->any())->method('isLocked')->willReturn(false); + + $status = \Magento\Framework\Indexer\StateInterface::STATUS_WORKING; + $this->model->setStatus($status); + $this->assertEquals($status, $this->model->getStatus()); + + $date = time(); + $this->model->setUpdated($date); + $this->assertEquals($date, $this->model->getUpdated()); + } + + /** + * @return array + */ + public function executeProvider() + { + return [ + [ + 'setStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_WORKING, + 'getStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_WORKING, + 'lock' => 'lock', + 'isLocked' => true + ], + [ + 'setStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_WORKING, + 'getStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_INVALID, + 'lock' => 'lock', + 'isLocked' => false + ], + [ + 'setStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_INVALID, + 'getStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_INVALID, + 'lock' => 'unlock', + 'isLocked' => false + ], + [ + 'setStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_VALID, + 'getStatus' => \Magento\Framework\Indexer\StateInterface::STATUS_VALID, + 'lock' => 'unlock', + 'isLocked' => false + ] + ]; + } + + /** + * @param string $setStatus + * @param string $getStatus + * @param bool $isLocked + * @dataProvider executeProvider + */ + public function testSetterAndGetterWithApplicationLock($setStatus, $getStatus, $lock, $isLocked) + { + $this->configReaderMock->expects($this->any())->method('get')->willReturn(true); + $this->lockManagerMock->expects($this->any())->method('isLocked')->willReturn($isLocked); + $this->lockManagerMock->expects($this->once())->method($lock); + $this->model->setStatus($setStatus); + $this->assertEquals($getStatus, $this->model->getStatus()); + } } diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Mview/View/StateTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Mview/View/StateTest.php index 80d78bedffc73..2841a0415ae94 100644 --- a/app/code/Magento/Indexer/Test/Unit/Model/Mview/View/StateTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Model/Mview/View/StateTest.php @@ -42,23 +42,34 @@ class StateTest extends TestCase */ protected $_resourceCollectionMock; + /** + * @var \Magento\Framework\Lock\LockManagerInterface|MockObject + */ + protected $lockManagerMock; + + /** + * @var \Magento\Framework\App\DeploymentConfig|MockObject + */ + protected $configReaderMock; + protected function setUp(): void { $this->_contextMock = $this->createPartialMock(Context::class, ['getEventDispatcher']); $eventManagerMock = $this->getMockForAbstractClass(ManagerInterface::class); $this->_contextMock->expects($this->any())->method('getEventDispatcher')->willReturn($eventManagerMock); $this->_registryMock = $this->createMock(Registry::class); - $this->_resourceMock = - $this->createMock(\Magento\Indexer\Model\ResourceModel\Mview\View\State::class); - $this->_resourceCollectionMock = $this->createMock( - Collection::class - ); - + $this->_resourceMock = $this->createMock(\Magento\Indexer\Model\ResourceModel\Mview\View\State::class); + $this->_resourceCollectionMock = $this->createMock(Collection::class); + $this->lockManagerMock = $this->createMock(\Magento\Framework\Lock\LockManagerInterface::class); + $this->configReaderMock = $this->createMock(\Magento\Framework\App\DeploymentConfig::class); $this->model = new State( $this->_contextMock, $this->_registryMock, $this->_resourceMock, - $this->_resourceCollectionMock + $this->_resourceCollectionMock, + [], + $this->lockManagerMock, + $this->configReaderMock ); } @@ -77,16 +88,74 @@ public function testBeforeSave() $this->assertNotNull($this->model->getUpdated()); } - public function testSetterAndGetter() + public function testSetterAndGetterWithoutApplicationLock() + { + $this->configReaderMock->expects($this->any())->method('get')->willReturn(false); + + $this->lockManagerMock->expects($this->any())->method('isLocked')->willReturn(false); + + $mode = \Magento\Framework\Mview\View\StateInterface::MODE_ENABLED; + $this->model->setMode($mode); + $this->assertEquals($mode, $this->model->getMode()); + + $status = \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING; + $this->model->setStatus($status); + $this->assertEquals($status, $this->model->getStatus()); + + $date = time(); + $this->model->setUpdated($date); + $this->assertEquals($date, $this->model->getUpdated()); + + $versionId = 99; + $this->model->setVersionId($versionId); + $this->assertEquals($versionId, $this->model->getVersionId()); + } + + /** + * @return array + */ + public function executeProvider() + { + return [ + [ + 'setStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING, + 'getStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING, + 'lock' => 'lock', + 'isLocked' => true + ], + [ + 'setStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING, + 'getStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_IDLE, + 'lock' => 'lock', + 'isLocked' => false + ], + [ + 'setStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_IDLE, + 'getStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_IDLE, + 'lock' => 'unlock', + 'isLocked' => false + ], + [ + 'setStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_SUSPENDED, + 'getStatus' => \Magento\Framework\Mview\View\StateInterface::STATUS_SUSPENDED, + 'lock' => 'unlock', + 'isLocked' => false + ] + ]; + } + + /** + * @param string $setStatus + * @param string $getStatus + * @param bool $isLocked + * @dataProvider executeProvider + */ + public function testSetterAndGetterWithApplicationLock($setStatus, $getStatus, $lock, $isLocked) { - $setData = 'data'; - $this->model->setMode($setData); - $this->assertEquals($setData, $this->model->getMode()); - $this->model->setStatus($setData); - $this->assertEquals($setData, $this->model->getStatus()); - $this->model->setUpdated($setData); - $this->assertEquals($setData, $this->model->getUpdated()); - $this->model->setVersionId($setData); - $this->assertEquals($setData, $this->model->getVersionId()); + $this->configReaderMock->expects($this->any())->method('get')->willReturn(true); + $this->lockManagerMock->expects($this->any())->method('isLocked')->willReturn($isLocked); + $this->lockManagerMock->expects($this->once())->method($lock); + $this->model->setStatus($setStatus); + $this->assertEquals($getStatus, $this->model->getStatus()); } } From eb96baf57060027ebef5e2df2ae10aa29ab1805f Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Fri, 15 Jan 2021 08:43:15 +0200 Subject: [PATCH 215/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- lib/web/mage/gallery/gallery.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index d6926720d7984..86ccdb858bf19 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -964,7 +964,7 @@ height: @fotorama_close_button; opacity: 0; right: 0; - top: 10%; + top: 0; transform: translate3d((@fotorama_close_button), (-@fotorama_close_button), 0); transition: opacity 0.3s ease-in-out; width: @fotorama_close_button; From 1b2187218fcfea7b52d283fe80a83ba607479613 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Fri, 15 Jan 2021 12:58:13 +0200 Subject: [PATCH 216/242] MC-39759: Navigation arrow buttons not visible after video starts on product image --- ...oseButtonHiddenProductVideoActionGroup.xml | 19 --------- ...extButtonHiddenProductVideoActionGroup.xml | 19 --------- ...revButtonHiddenProductVideoActionGroup.xml | 19 --------- ...roductVideoNavigationArrowsActionGroup.xml | 42 +++++++++++++++++++ ...lickCloseButtonProductVideoActionGroup.xml | 21 ---------- ...ClickNextButtonProductVideoActionGroup.xml | 21 ---------- ...ClickPlayButtonProductVideoActionGroup.xml | 20 --------- ...ClickPrevButtonProductVideoActionGroup.xml | 21 ---------- ...eoVideoControlButtonsOnProductPageTest.xml | 22 +--------- 9 files changed, 44 insertions(+), 160 deletions(-) delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml create mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoNavigationArrowsActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml delete mode 100644 app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml deleted file mode 100644 index edd837db6c31c..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertCloseButtonHiddenProductVideoActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?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"> - <!-- Assert that close button is hidden on Storefront Product page --> - <actionGroup name="AssertCloseButtonHiddenProductVideoActionGroup"> - <annotations> - <description>Validates that the close button is absent on the Storefront Product page.</description> - </annotations> - - <dontSeeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="dontSeeCloseVideo"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml deleted file mode 100644 index 6778ade18b496..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertNextButtonHiddenProductVideoActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?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"> - <!-- Assert that next button is hidden on Storefront Product page --> - <actionGroup name="AssertNextButtonHiddenProductVideoActionGroup"> - <annotations> - <description>Validates that the next button is absent on the Storefront Product page.</description> - </annotations> - - <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml deleted file mode 100644 index 1a588f4a23f84..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertPrevButtonHiddenProductVideoActionGroup.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?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"> - <!-- Assert that previous button is hidden on Storefront Product page --> - <actionGroup name="AssertPrevButtonHiddenProductVideoActionGroup"> - <annotations> - <description>Validates that the previous button is absent on the Storefront Product page.</description> - </annotations> - - <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoNavigationArrowsActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoNavigationArrowsActionGroup.xml new file mode 100644 index 0000000000000..d0673dfc1adb7 --- /dev/null +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoNavigationArrowsActionGroup.xml @@ -0,0 +1,42 @@ +<?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"> + <!-- Assert the navigation arrows on Storefront Product page --> + <actionGroup name="AssertProductVideoNavigationArrowsActionGroup"> + <annotations> + <description>Validates the navigation arrows on the Storefront Product page.</description> + </annotations> + <arguments> + <argument name="videoType" type="string" defaultValue="vimeo"/> + </arguments> + + <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButton"/> + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> + <seeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="seeNextButton"/> + <click selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="clickNextButton"/> + <seeElement selector="{{StorefrontProductInfoMainSection.productVideo(videoType)}}" stepKey="seeProductVideoDataType"/> + + <dontSeeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="dontSeeCloseVideo"/> + + <click selector="{{StorefrontProductInfoMainSection.clickPlayVideo}}" stepKey="clickToPlayVideo"/> + <wait stepKey="waitFiveSecondsToPlayVideo" time="5"/> + + <dontSeeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="dontSeePrevButtonSecond"/> + <dontSeeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="dontSeeNextButton"/> + + <seeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="seeCloseVideo"/> + <click selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="clickToCloseVideo"/> + <wait stepKey="waitTwoSecondsToCloseVideo" time="2"/> + + <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImageSecond"/> + <seeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="seePrevButton"/> + <click selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="clickPrevButton"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml deleted file mode 100644 index a18e98eebb48c..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickCloseButtonProductVideoActionGroup.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?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"> - <!-- Click close button in product video on Storefront Product page --> - <actionGroup name="ClickCloseButtonProductVideoActionGroup"> - <annotations> - <description>Click close button in product video on the Storefront Product page.</description> - </annotations> - - <seeElement selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}" stepKey="seeCloseVideo"/> - <click stepKey="clickCloseVideo" selector="{{StorefrontProductInfoMainSection.clickCloseVideo}}"/> - <wait stepKey="waitTwoSecondsToCloseVideo" time="2"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml deleted file mode 100644 index eb7c94514fa24..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickNextButtonProductVideoActionGroup.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?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"> - <!-- Click next button in product video on Storefront Product page --> - <actionGroup name="ClickNextButtonProductVideoActionGroup"> - <annotations> - <description>Click next button in product video on the Storefront Product page.</description> - </annotations> - - <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> - <seeElement selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="seeNextButton"/> - <click selector="{{StorefrontProductMediaSection.imageNextButton}}" stepKey="clickNextButton"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml deleted file mode 100644 index 481097b488be8..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPlayButtonProductVideoActionGroup.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?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"> - <!-- Click play button in product video on Storefront Product page --> - <actionGroup name="ClickPlayButtonProductVideoActionGroup"> - <annotations> - <description>Click play button in product video on the Storefront Product page.</description> - </annotations> - - <click selector="{{StorefrontProductInfoMainSection.clickPlayVideo}}" stepKey="clickToPlayVideo"/> - <wait stepKey="waitFiveSecondsToPlayVideo" time="5"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml deleted file mode 100644 index aa32812997624..0000000000000 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/ClickPrevButtonProductVideoActionGroup.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?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"> - <!-- Click previous button in product video on Storefront Product page --> - <actionGroup name="ClickPrevButtonProductVideoActionGroup"> - <annotations> - <description>Click previous button in product video on the Storefront Product page.</description> - </annotations> - - <moveMouseOver selector="{{StorefrontProductMediaSection.mainImageForJsActions}}" stepKey="hoverOverImage"/> - <seeElement selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="seePrevButton"/> - <click selector="{{StorefrontProductMediaSection.imagePrevButton}}" stepKey="clickPrevButton"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml index a4719fa281f29..a60a5526498ce 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/Test/VimeoVideoControlButtonsOnProductPageTest.xml @@ -50,27 +50,9 @@ <argument name="productUrl" value="$createProduct.custom_attributes[url_key]$"/> </actionGroup> - <!-- Click next button --> - <actionGroup ref="AssertPrevButtonHiddenProductVideoActionGroup" stepKey="assertPrevButtonIsHidden"/> - <actionGroup ref="ClickNextButtonProductVideoActionGroup" stepKey="clickNextNavigationButton"/> - - <!-- Assert product video present in the storefront product page --> - <actionGroup ref="AssertProductVideoStorefrontProductPageActionGroup" stepKey="assertProductVideoPresentInStorefrontProductPage"> + <!-- Check the navigation arrows on Storefront Product page --> + <actionGroup ref="AssertProductVideoNavigationArrowsActionGroup" stepKey="assertProductVideoNavigationArrowsOnStorefrontProductPage"> <argument name="videoType" value="vimeo"/> </actionGroup> - <actionGroup ref="AssertCloseButtonHiddenProductVideoActionGroup" stepKey="assertCloseVideoButtonIsHidden"/> - - <!-- Click Play video button --> - <actionGroup ref="ClickPlayButtonProductVideoActionGroup" stepKey="clickPlayVideoButton"/> - - <!-- Assert product navigation arrows --> - <actionGroup ref="AssertPrevButtonHiddenProductVideoActionGroup" stepKey="assertPrevButtonIsHidden2"/> - <actionGroup ref="AssertNextButtonHiddenProductVideoActionGroup" stepKey="assertNextButtonIsHidden"/> - - <!-- Click Close video button --> - <actionGroup ref="ClickCloseButtonProductVideoActionGroup" stepKey="clickCloseVideoButton"/> - - <!-- Click previous button --> - <actionGroup ref="ClickPrevButtonProductVideoActionGroup" stepKey="clickPrevNavigationButton"/> </test> </tests> From dfb9899518f89aa5067b3315273ce1019f8529f9 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Fri, 15 Jan 2021 17:06:07 +0200 Subject: [PATCH 217/242] MC-35640: The product is not added to the cart --- .../Test/Mftf/Page/StorefrontCategoryPage.xml | 15 +++++++++++++++ ...ection.xml => StorefrontMsrpPopupSection.xml} | 4 ++-- ...pProductToCartFromPopupOnCategoryPageTest.xml | 16 ++++++++-------- 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml rename app/code/Magento/Msrp/Test/Mftf/Section/{StorefrontMsrpSection.xml => StorefrontMsrpPopupSection.xml} (65%) diff --git a/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml b/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml new file mode 100644 index 0000000000000..e51d785f462f0 --- /dev/null +++ b/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml @@ -0,0 +1,15 @@ +<?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="StorefrontCategoryPage" url="/{{var1}}.html" area="storefront" module="Magento_Catalog" parameterized="true"> + <section name="StorefrontMsrpPopupSection"/> + <section name="StorefrontMsrpCategorySection"/> + </page> +</pages> diff --git a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpPopupSection.xml similarity index 65% rename from app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml rename to app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpPopupSection.xml index 98c4ad7245dc4..8f4a5952bce67 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpSection.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpPopupSection.xml @@ -7,7 +7,7 @@ --> <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="StorefrontMsrpSection"> - <element name="popupAddToCartButton" type="button" selector="#map-popup-click-for-price .action.tocart" timeout="30"/> + <section name="StorefrontMsrpPopupSection"> + <element name="addToCartButton" type="button" selector="#map-popup-click-for-price .action.tocart" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml index 839ddd99786da..913de59ef592d 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml @@ -12,12 +12,12 @@ <annotations> <features value="Msrp"/> <stories value="Minimum advertised price"/> - <title value="Add simple product with MAP to cart from popup on category page"/> - <description value="Check that simple product with MAP is successfully added to cart from popup on category page"/> + <title value="Add simple product with minimum advertised price to cart from popup on category page"/> + <description value="Check that simple product with minimum advertised price is successfully added to cart from popup on category page"/> <severity value="MAJOR"/> <testCaseId value="MC-40419"/> <useCaseId value="MC-35640"/> - <group value="Msrp"/> + <group value="msrp"/> </annotations> <before> <!-- Enable Minimum advertised Price --> @@ -51,15 +51,15 @@ <!-- Grab and verify MAP price --> <grabTextFrom selector="{{StorefrontMsrpCategorySection.mapPrice($createProduct.name$)}}" stepKey="grabMapPrice"/> <assertEquals stepKey="assertMapPrice"> - <actualResult type="const">($grabMapPrice)</actualResult> + <actualResult type="variable">grabMapPrice</actualResult> <expectedResult type="string">${{ApiProductMsrp.value}}</expectedResult> </assertEquals> <!-- Open 'Click for price' popup and click 'Add to Cart' button --> <click selector="{{StorefrontMsrpCategorySection.clickForPrice($createProduct.name$)}}" stepKey="clickForPrice"/> - <waitForElementVisible selector="{{StorefrontMsrpSection.popupAddToCartButton}}" stepKey="waitForAddToCartButton"/> - <click selector="{{StorefrontMsrpSection.popupAddToCartButton}}" stepKey="clickAddToCartButton"/> - <waitForElementVisible selector="{{StorefrontCategoryMainSection.SuccessMsg}}" stepKey="waitForSuccessMessage"/> - <see selector="{{StorefrontCategoryMainSection.SuccessMsg}}" userInput="You added $createProduct.name$ to your shopping cart." stepKey="assertSuccessMessage"/> + <waitForElementVisible selector="{{StorefrontMsrpPopupSection.addToCartButton}}" stepKey="waitForAddToCartButton"/> + <click selector="{{StorefrontMsrpPopupSection.addToCartButton}}" stepKey="clickAddToCartButton"/> + <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> + <see selector="{{StorefrontMessagesSection.success}}" userInput="You added $createProduct.name$ to your shopping cart." stepKey="assertSuccessMessage"/> </test> </tests> From b5906483ef63b1fc54e41c5fba85f98c31379d60 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Fri, 15 Jan 2021 17:26:58 +0200 Subject: [PATCH 218/242] MC-35640: The product is not added to the cart --- .../Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml | 1 + .../Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml | 1 - ...tegorySection.xml => StorefrontCategoryProductSection.xml} | 2 +- ...orefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename app/code/Magento/Msrp/Test/Mftf/Section/{StorefrontMsrpCategorySection.xml => StorefrontCategoryProductSection.xml} (93%) diff --git a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml index 416e0d27a1824..e0640ba39acd4 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Page/StorefrontCategoryPage.xml @@ -11,5 +11,6 @@ <page name="StorefrontCategoryPage" url="/{{var1}}.html" area="storefront" module="Magento_Catalog" parameterized="true"> <section name="StorefrontCategoryMainSection"/> <section name="WYSIWYGToolbarSection"/> + <section name="StorefrontCategoryProductSection"/> </page> </pages> diff --git a/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml b/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml index e51d785f462f0..4fd3f3f445079 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Page/StorefrontCategoryPage.xml @@ -10,6 +10,5 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="StorefrontCategoryPage" url="/{{var1}}.html" area="storefront" module="Magento_Catalog" parameterized="true"> <section name="StorefrontMsrpPopupSection"/> - <section name="StorefrontMsrpCategorySection"/> </page> </pages> diff --git a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontCategoryProductSection.xml similarity index 93% rename from app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml rename to app/code/Magento/Msrp/Test/Mftf/Section/StorefrontCategoryProductSection.xml index 2f07d92ee412a..87cb7905ff54d 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontMsrpCategorySection.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -7,7 +7,7 @@ --> <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="StorefrontMsrpCategorySection"> + <section name="StorefrontCategoryProductSection"> <element name="clickForPrice" type="button" selector="//a[normalize-space() = '{{productName}}']/following::div[@data-role='priceBox']/a[@class='action map-show-info']" parameterized="true" timeout="30"/> <element name="mapPrice" type="button" selector="//a[normalize-space() = '{{productName}}']/following::div[@data-role='priceBox']//span[contains(@class, 'price-msrp_price')]" parameterized="true" timeout="30"/> </section> diff --git a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml index 913de59ef592d..86732ba1e18bf 100644 --- a/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml +++ b/app/code/Magento/Msrp/Test/Mftf/Test/StorefrontAddMapProductToCartFromPopupOnCategoryPageTest.xml @@ -49,14 +49,14 @@ </actionGroup> <!-- Grab and verify MAP price --> - <grabTextFrom selector="{{StorefrontMsrpCategorySection.mapPrice($createProduct.name$)}}" stepKey="grabMapPrice"/> + <grabTextFrom selector="{{StorefrontCategoryProductSection.mapPrice($createProduct.name$)}}" stepKey="grabMapPrice"/> <assertEquals stepKey="assertMapPrice"> <actualResult type="variable">grabMapPrice</actualResult> <expectedResult type="string">${{ApiProductMsrp.value}}</expectedResult> </assertEquals> <!-- Open 'Click for price' popup and click 'Add to Cart' button --> - <click selector="{{StorefrontMsrpCategorySection.clickForPrice($createProduct.name$)}}" stepKey="clickForPrice"/> + <click selector="{{StorefrontCategoryProductSection.clickForPrice($createProduct.name$)}}" stepKey="clickForPrice"/> <waitForElementVisible selector="{{StorefrontMsrpPopupSection.addToCartButton}}" stepKey="waitForAddToCartButton"/> <click selector="{{StorefrontMsrpPopupSection.addToCartButton}}" stepKey="clickAddToCartButton"/> <waitForElementVisible selector="{{StorefrontMessagesSection.success}}" stepKey="waitForSuccessMessage"/> From e7f760838a496e88c0cda5b42544fe5194c3efdb Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 15 Jan 2021 18:34:02 +0200 Subject: [PATCH 219/242] MC-38088: [MFTF] Flaky AdminSimpleProductRemoveImagesTest --- .../ActionGroup/AdminOpenProductImagesSectionActionGroup.xml | 1 + .../AdminSimpleProductRemoveImagesTest.xml | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml index 4d49b13a8bf5a..407cc339de501 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml @@ -12,6 +12,7 @@ <annotations> <description>Requires the navigation to the Product page. Opens 'Image and Videos' section.</description> </annotations> + <scrollTo selector="{{AdminProductImagesSection.productImagesToggle}}" stepKey="scrollToProductImagesTab"/> <conditionalClick selector="{{AdminProductImagesSection.productImagesToggle}}" dependentSelector="{{AdminProductImagesSection.imageUploadButton}}" visible="false" stepKey="openProductImagesSection"/> <waitForElementVisible selector="{{AdminProductImagesSection.imageUploadButton}}" stepKey="waitForImageUploadButton"/> </actionGroup> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml index 8b3d1a2a6ca2c..bb6a3417e7b74 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml @@ -29,8 +29,7 @@ <after> <deleteData createDataKey="category" stepKey="deletePreReqCategory"/> <deleteData createDataKey="product" stepKey="deleteProduct"/> - <actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="goToProductsPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearProductGridFilters"/> + <actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </after> @@ -50,6 +49,7 @@ <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages"/> <!-- Upload and set Base image --> + <waitForPageLoad stepKey="waitBeforeAttachImages"/> <attachFile selector="{{AdminProductImagesSection.imageFileUpload}}" userInput="adobe-base.jpg" stepKey="attach1"/> <waitForPageLoad stepKey="waitForUpload1"/> <click selector="{{AdminProductImagesSection.nthProductImage('1')}}" stepKey="openImageDetails1"/> @@ -116,6 +116,7 @@ <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages2"/> <!-- Remove all images --> + <waitForPageLoad stepKey="waitBeforeRemoveImages"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('1')}}" stepKey="removeImage1"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('2')}}" stepKey="removeImage2"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('3')}}" stepKey="removeImage3"/> From e95b68fe2014426d5d92a06f3257981e3d2be1c5 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 18 Jan 2021 10:03:22 +0200 Subject: [PATCH 220/242] MC-36149: [CLOUD] 'Be the first to review this product' link is not changed after admin has approved the review --- .../Review/Block/Product/ReviewRenderer.php | 16 ++++++++-------- ...ectByEntityCode.php => AppendSummaryData.php} | 6 ++++-- app/code/Magento/Review/Model/ReviewSummary.php | 2 +- ...ityCodeTest.php => AppendSummaryDataTest.php} | 10 +++++----- 4 files changed, 18 insertions(+), 16 deletions(-) rename app/code/Magento/Review/Model/{AppendSummaryDataToObjectByEntityCode.php => AppendSummaryData.php} (91%) rename app/code/Magento/Review/Test/Unit/Model/{AppendSummaryDataToObjectByEntityCodeTest.php => AppendSummaryDataTest.php} (93%) diff --git a/app/code/Magento/Review/Block/Product/ReviewRenderer.php b/app/code/Magento/Review/Block/Product/ReviewRenderer.php index c6987a4ee35c1..7a881efa088df 100644 --- a/app/code/Magento/Review/Block/Product/ReviewRenderer.php +++ b/app/code/Magento/Review/Block/Product/ReviewRenderer.php @@ -13,7 +13,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; -use Magento\Review\Model\AppendSummaryDataToObjectByEntityCodeFactory; +use Magento\Review\Model\AppendSummaryDataFactory; use Magento\Review\Model\Review; use Magento\Review\Model\ReviewFactory; use Magento\Review\Model\ReviewSummaryFactory; @@ -48,29 +48,29 @@ class ReviewRenderer extends Template implements ReviewRendererInterface private $reviewSummaryFactory; /** - * @var AppendSummaryDataToObjectByEntityCodeFactory + * @var AppendSummaryDataFactory */ - private $appendSummaryDataToObjectByEntityCodeFactory; + private $appendSummaryDataFactory; /** * @param Context $context * @param ReviewFactory $reviewFactory * @param array $data * @param ReviewSummaryFactory|null $reviewSummaryFactory - * @param AppendSummaryDataToObjectByEntityCodeFactory|null $appendSummaryDataToObjectByEntityCodeFactory + * @param AppendSummaryDataFactory|null $appendSummaryDataFactory */ public function __construct( Context $context, ReviewFactory $reviewFactory, array $data = [], ReviewSummaryFactory $reviewSummaryFactory = null, - AppendSummaryDataToObjectByEntityCodeFactory $appendSummaryDataToObjectByEntityCodeFactory = null + AppendSummaryDataFactory $appendSummaryDataFactory = null ) { $this->_reviewFactory = $reviewFactory; $this->reviewSummaryFactory = $reviewSummaryFactory ?? ObjectManager::getInstance()->get(ReviewSummaryFactory::class); - $this->appendSummaryDataToObjectByEntityCodeFactory = $appendSummaryDataToObjectByEntityCodeFactory ?? - ObjectManager::getInstance()->get(AppendSummaryDataToObjectByEntityCodeFactory::class); + $this->appendSummaryDataFactory = $appendSummaryDataFactory ?? + ObjectManager::getInstance()->get(AppendSummaryDataFactory::class); parent::__construct($context, $data); } @@ -104,7 +104,7 @@ public function getReviewsSummaryHtml( $displayIfNoReviews = false ) { if ($product->getRatingSummary() === null) { - $this->appendSummaryDataToObjectByEntityCodeFactory->create() + $this->appendSummaryDataFactory->create() ->execute( $product, $this->_storeManager->getStore()->getId(), diff --git a/app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php b/app/code/Magento/Review/Model/AppendSummaryData.php similarity index 91% rename from app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php rename to app/code/Magento/Review/Model/AppendSummaryData.php index 6307a86b2c49a..e5329dedc8403 100644 --- a/app/code/Magento/Review/Model/AppendSummaryDataToObjectByEntityCode.php +++ b/app/code/Magento/Review/Model/AppendSummaryData.php @@ -13,7 +13,7 @@ /** * Add review summary data to object by its entity code */ -class AppendSummaryDataToObjectByEntityCode +class AppendSummaryData { /** * @var SummaryCollectionFactory @@ -30,6 +30,8 @@ public function __construct( } /** + * Append summary data to object filtered by its entity code + * * @param AbstractModel $object * @param int $storeId * @param string $entityCode @@ -45,7 +47,7 @@ public function execute(AbstractModel $object, int $storeId, string $entityCode) 'main_table.entity_type = review_entity.entity_id', 'entity_code' ) - ->where('entity_pk_value IN (?)', $object->getId()) + ->where('entity_pk_value = ?', $object->getId()) ->where('entity_code = ?', $entityCode); $summaryItem = $summaryCollection->getFirstItem(); diff --git a/app/code/Magento/Review/Model/ReviewSummary.php b/app/code/Magento/Review/Model/ReviewSummary.php index ff1a2c4e3a76e..a66dc73b35293 100644 --- a/app/code/Magento/Review/Model/ReviewSummary.php +++ b/app/code/Magento/Review/Model/ReviewSummary.php @@ -14,7 +14,7 @@ * ReviewSummary model. * * @deprecated Filtering collection by entity_type ID leads to wrong result if AUTO_INCREMENT begins not form 1. - * @see \Magento\Review\Model\AppendSummaryDataToObjectByEntityCode + * @see \Magento\Review\Model\AppendSummaryData */ class ReviewSummary { diff --git a/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php b/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataTest.php similarity index 93% rename from app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php rename to app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataTest.php index e42ca82945d5e..0d624cad551ce 100644 --- a/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataToObjectByEntityCodeTest.php +++ b/app/code/Magento/Review/Test/Unit/Model/AppendSummaryDataTest.php @@ -9,7 +9,7 @@ use Magento\Catalog\Model\Product; use Magento\Framework\DB\Select; -use Magento\Review\Model\AppendSummaryDataToObjectByEntityCode; +use Magento\Review\Model\AppendSummaryData; use Magento\Review\Model\ResourceModel\Review\Summary as ResourceSummary; use Magento\Review\Model\ResourceModel\Review\Summary\Collection as SummaryCollection; use Magento\Review\Model\ResourceModel\Review\Summary\CollectionFactory as SummaryCollectionFactory; @@ -18,9 +18,9 @@ use PHPUnit\Framework\TestCase; /** - * Unit tests for \Magento\Review\Model\AppendSummaryDataToObjectByEntityCode class + * Unit tests for \Magento\Review\Model\AppendSummaryData class */ -class AppendSummaryDataToObjectByEntityCodeTest extends TestCase +class AppendSummaryDataTest extends TestCase { /** * @var SummaryCollectionFactory|MockObject @@ -53,7 +53,7 @@ class AppendSummaryDataToObjectByEntityCodeTest extends TestCase private $resourceSummaryMock; /** - * @var AppendSummaryDataToObjectByEntityCode + * @var AppendSummaryData */ private $model; @@ -99,7 +99,7 @@ protected function setUp(): void ->onlyMethods(['getTable']) ->getMock(); - $this->model = new AppendSummaryDataToObjectByEntityCode( + $this->model = new AppendSummaryData( $this->summaryCollectionFactoryMock ); } From 6f62488eaca80a4c69ea41a5b93c780e31d2f801 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 18 Jan 2021 10:42:26 +0200 Subject: [PATCH 221/242] MC-40453: 2.4-develop-sidecar-pr10 PR stabilization --- .../Customer/Model/CustomerMetadataTest.php | 172 ++++++++++-------- 1 file changed, 101 insertions(+), 71 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php index 63d7019ee4f61..56e0174c98c7f 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php @@ -3,15 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Customer\Model; use Magento\Customer\Api\CustomerMetadataInterface; use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\TestFramework\Helper\CacheCleaner; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; -class CustomerMetadataTest extends \PHPUnit\Framework\TestCase +/** + * Checks customer metadata + * + * @magentoDbIsolation enabled + */ +class CustomerMetadataTest extends TestCase { /** @var CustomerRepositoryInterface */ private $customerRepository; @@ -22,16 +30,18 @@ class CustomerMetadataTest extends \PHPUnit\Framework\TestCase /** @var CustomerMetadataInterface */ private $serviceTwo; - /** - * @var \Magento\Framework\Api\ExtensibleDataObjectConverter - */ + /** @var ExtensibleDataObjectConverter */ private $extensibleDataObjectConverter; + /** + * @inheritdoc + */ protected function setUp(): void { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $objectManager = Bootstrap::getObjectManager(); $objectManager->configure( - [\Magento\Framework\Api\ExtensionAttribute\Config\Reader::class => [ + [ + \Magento\Framework\Api\ExtensionAttribute\Config\Reader::class => [ 'arguments' => [ 'fileResolver' => ['instance' => \Magento\Customer\Model\FileResolverStub::class], ], @@ -44,13 +54,73 @@ protected function setUp(): void $this->service = $objectManager->create(\Magento\Customer\Api\CustomerMetadataInterface::class); $this->serviceTwo = $objectManager->create(\Magento\Customer\Api\CustomerMetadataInterface::class); $this->extensibleDataObjectConverter = $objectManager->get( - \Magento\Framework\Api\ExtensibleDataObjectConverter::class + ExtensibleDataObjectConverter::class ); } - public function testGetCustomAttributesMetadata() + /** + * @magentoDataFixture Magento/Customer/_files/attribute_user_defined_custom_attribute.php + * + * @return void + */ + public function testGetCustomAttributesMetadataWithCustomAttributes(): void + { + $customAttributesMetadata = $this->service->getCustomAttributesMetadata(); + // Verify the consistency of getCustomAttributesMetadata() function from the 2nd call of the same service + $customAttributesMetadata1 = $this->service->getCustomAttributesMetadata(); + $this->assertEquals( + $customAttributesMetadata, + $customAttributesMetadata1, + 'Different custom attribute metadata returned from the 2nd call of the same service' + ); + // Verify the consistency of getCustomAttributesMetadata() function from the 2nd service + $customAttributesMetadata2 = $this->serviceTwo->getCustomAttributesMetadata(); + $this->assertEquals( + $customAttributesMetadata, + $customAttributesMetadata2, + 'Different custom attribute metadata returned from the 2nd service' + ); + + $expectedCustomAttributeCodeArray = ['custom_attribute1', 'custom_attribute2', 'customer_image']; + $actual = []; + foreach ($customAttributesMetadata as $attribute) { + $actual[] = $attribute->getAttributeCode(); + } + $this->assertEquals( + $expectedCustomAttributeCodeArray, + array_intersect($expectedCustomAttributeCodeArray, $actual), + "Expected attributes not returned from the service." + ); + + // Verify the consistency of custom attribute metadata from two calls of the same service + // after getAttributeCode was called + foreach ($customAttributesMetadata1 as $attribute) { + $attribute->getAttributeCode(); + } + $this->assertEquals( + $customAttributesMetadata, + $customAttributesMetadata1, + 'Custom attribute metadata from the same service became different after getAttributeCode was called' + ); + + // Verify the consistency of custom attribute metadata from two services + // after getAttributeCode was called + foreach ($customAttributesMetadata2 as $attribute) { + $attribute->getAttributeCode(); + } + $this->assertEquals( + $customAttributesMetadata, + $customAttributesMetadata2, + 'Custom attribute metadata from two services are different after getAttributeCode was called' + ); + } + + /** + * @return void + */ + public function testGetCustomAttributesMetadata(): void { - $customAttributesMetadataQty = count($this->service->getCustomAttributesMetadata()) ; + $customAttributesMetadataQty = count($this->service->getCustomAttributesMetadata()); // Verify the consistency of getCustomerAttributeMetadata() function from the 2nd call of the same service $customAttributesMetadata1Qty = count($this->service->getCustomAttributesMetadata()); @@ -71,8 +141,10 @@ public function testGetCustomAttributesMetadata() /** * @magentoAppIsolation enabled + * + * @return void */ - public function testGetNestedOptionsCustomerAttributesMetadata() + public function testGetNestedOptionsCustomerAttributesMetadata(): void { $nestedOptionsAttribute = 'store_id'; $customAttributesMetadata = $this->service->getAttributeMetadata($nestedOptionsAttribute); @@ -126,63 +198,10 @@ public function testGetNestedOptionsCustomerAttributesMetadata() /** * @magentoDataFixture Magento/Customer/_files/attribute_user_defined_custom_attribute.php + * + * @return void */ - public function testGetCustomAttributesMetadataWithCustomAttributes() - { - $customAttributesMetadata = $this->service->getCustomAttributesMetadata(); - // Verify the consistency of getCustomAttributesMetadata() function from the 2nd call of the same service - $customAttributesMetadata1 = $this->service->getCustomAttributesMetadata(); - $this->assertEquals( - $customAttributesMetadata, - $customAttributesMetadata1, - 'Different custom attribute metadata returned from the 2nd call of the same service' - ); - // Verify the consistency of getCustomAttributesMetadata() function from the 2nd service - $customAttributesMetadata2 = $this->serviceTwo->getCustomAttributesMetadata(); - $this->assertEquals( - $customAttributesMetadata, - $customAttributesMetadata2, - 'Different custom attribute metadata returned from the 2nd service' - ); - - $expectedCustomAttributeCodeArray = ['custom_attribute1', 'custom_attribute2', 'customer_image']; - $actual = []; - foreach ($customAttributesMetadata as $attribute) { - $actual[] = $attribute->getAttributeCode(); - } - $this->assertEquals( - $expectedCustomAttributeCodeArray, - array_intersect($expectedCustomAttributeCodeArray, $actual), - "Expected attributes not returned from the service." - ); - - // Verify the consistency of custom attribute metadata from two calls of the same service - // after getAttributeCode was called - foreach ($customAttributesMetadata1 as $attribute) { - $attribute->getAttributeCode(); - } - $this->assertEquals( - $customAttributesMetadata, - $customAttributesMetadata1, - 'Custom attribute metadata from the same service became different after getAttributeCode was called' - ); - - // Verify the consistency of custom attribute metadata from two services - // after getAttributeCode was called - foreach ($customAttributesMetadata2 as $attribute) { - $attribute->getAttributeCode(); - } - $this->assertEquals( - $customAttributesMetadata, - $customAttributesMetadata2, - 'Custom attribute metadata from two services are different after getAttributeCode was called' - ); - } - - /** - * @magentoDataFixture Magento/Customer/_files/attribute_user_defined_custom_attribute.php - */ - public function testGetAllAttributesMetadataWithCustomAttribute() + public function testGetAllAttributesMetadataWithCustomAttribute(): void { $allAttributesMetadata = $this->service->getAllAttributesMetadata(); @@ -205,8 +224,10 @@ public function testGetAllAttributesMetadataWithCustomAttribute() /** * @magentoDataFixture Magento/Customer/_files/customer.php + * + * @return void */ - public function testGetCustomerAttributeMetadata() + public function testGetCustomerAttributeMetadata(): void { // Expect these attributes to exist but do not check the value $expectAttrsWOutVals = ['created_at', 'updated_at']; @@ -298,7 +319,10 @@ public function testGetCustomerAttributeMetadata() $this->assertEmpty($expectAttrsWithVals); } - public function testGetCustomerAttributeMetadataNoSuchEntity() + /** + * @return void + */ + public function testGetCustomerAttributeMetadataNoSuchEntity(): void { try { $this->service->getAttributeMetadata('wrong_attribute_code'); @@ -333,7 +357,10 @@ public function testGetCustomerAttributeMetadataNoSuchEntity() } } - public function testGetAttributes() + /** + * @return void + */ + public function testGetAttributes(): void { $formAttributesMetadata = $this->service->getAttributes('adminhtml_customer'); $this->assertCount(14, $formAttributesMetadata, "Invalid number of attributes for the specified form."); @@ -383,9 +410,12 @@ public function testGetAttributes() ); } + /** + * @inheritdoc + */ protected function tearDown(): void { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $objectManager = Bootstrap::getObjectManager(); /* @var \Magento\Framework\Config\CacheInterface $cache */ $cache = $objectManager->create(\Magento\Framework\Config\CacheInterface::class); From bf2207aa47c53f2b63d0dea74bdf93c20e4a7d0b Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 18 Jan 2021 11:39:39 +0200 Subject: [PATCH 222/242] MC-40059: Create automated test for: "Subscribe to price alert" --- .../Edit/Tab/Alerts/AbstractAlertTest.php | 91 +++++++++++++++++ .../Product/Edit/Tab/Alerts/PriceTest.php | 99 +++++++++++++++++++ .../Product/Edit/Tab/Alerts/StockTest.php | 50 ++++++---- .../Adminhtml/Product/AbstractAlertTest.php | 76 ++++++++++++++ .../Adminhtml/Product/AlertsPriceGridTest.php | 63 ++++++++++++ .../Adminhtml/Product/AlertsStockGridTest.php | 63 ++++++++++++ .../Product/Form/Modifier/AlertsTest.php | 10 +- .../_files/price_alert_on_second_website.php | 66 +++++++++++++ ...price_alert_on_second_website_rollback.php | 53 ++++++++++ .../_files/product_alert_rollback.php | 6 ++ .../_files/simple_product_with_two_alerts.php | 59 +++++++++++ ...imple_product_with_two_alerts_rollback.php | 39 ++++++++ 12 files changed, 652 insertions(+), 23 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/AbstractAlertTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/PriceTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AbstractAlertTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsPriceGridTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsStockGridTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts.php create mode 100644 dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/AbstractAlertTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/AbstractAlertTest.php new file mode 100644 index 0000000000000..8ac709c584648 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/AbstractAlertTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts; + +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Module\Manager; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Base alert's tab test logic + */ +abstract class AbstractAlertTest extends TestCase +{ + /** @var ObjectManagerInterface */ + protected $objectManager; + + /** @var RequestInterface */ + protected $request; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** @var ProductResource */ + private $productResource; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + + $objectManager = Bootstrap::getObjectManager(); + /** @var Manager $moduleManager */ + $moduleManager = $objectManager->get(Manager::class); + //This check is needed because module Magento_Catalog is independent of Magento_ProductAlert + if (!$moduleManager->isEnabled('Magento_ProductAlert')) { + self::markTestSkipped('Magento_ProductAlert module disabled.'); + } + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + $this->request = $this->objectManager->get(RequestInterface::class); + $this->productResource = $this->objectManager->get(ProductResource::class); + } + + /** + * Prepare request + * + * @param string|null $sku + * @param string|null $storeCode + * @return void + */ + protected function prepareRequest(?string $sku = null, ?string $storeCode = null): void + { + $productId = (int)$this->productResource->getIdBySku($sku); + $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : null; + $this->request->setParams(['id' => $productId, 'store' => $storeId]); + } + + /** + * Assert grid url + * + * @param string $url + * @param string|null $storeCode + * @return void + */ + protected function assertGridUrl(string $url, ?string $storeCode): void + { + $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : Store::DEFAULT_STORE_ID; + $this->assertStringContainsString(sprintf('/store/%s', $storeId), $url); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/PriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/PriceTest.php new file mode 100644 index 0000000000000..38f03a4558507 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/PriceTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts; + +use Magento\Framework\View\LayoutInterface; + +/** + * Check price alert grid + * + * @see \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts\Price + * + * @magentoAppArea adminhtml + */ +class PriceTest extends AbstractAlertTest +{ + /** @var Price */ + private $block; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Price::class); + } + + /** + * @dataProvider alertsDataProvider + * + * @magentoDbIsolation disabled + * + * @magentoDataFixture Magento/ProductAlert/_files/product_alert.php + * @magentoDataFixture Magento/ProductAlert/_files/price_alert_on_second_website.php + * + * @param string $sku + * @param string $expectedEmail + * @param string|null $storeCode + * @return void + */ + public function testGridCollectionWithStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void + { + $this->prepareRequest($sku, $storeCode); + $collection = $this->block->getPreparedCollection(); + $this->assertCount(1, $collection); + $this->assertEquals($expectedEmail, $collection->getFirstItem()->getEmail()); + } + + /** + * @return array + */ + public function alertsDataProvider(): array + { + return [ + 'without_store_id_filter' => [ + 'product_sku' => 'simple', + 'expected_customer_emails' => 'customer@example.com', + ], + 'with_store_id_filter' => [ + 'product_sku' => 'simple_on_second_website_for_price_alert', + 'expected_customer_emails' => 'customer_second_ws_with_addr@example.com', + 'store_code' => 'fixture_third_store', + ], + ]; + } + + /** + * @dataProvider storeProvider + * + * @param string|null $storeCode + * @return void + */ + public function testGetGridUrl(?string $storeCode): void + { + $this->prepareRequest(null, $storeCode); + $this->assertGridUrl($this->block->getGridUrl(), $storeCode); + } + + /** + * @return array + */ + public function storeProvider(): array + { + return [ + 'without_store_id_param' => [ + 'store_code' => null, + ], + 'with_store_id_param' => [ + 'store_code' => 'default', + ], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php index b9ccfd6d52458..b221695a78e3b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Alerts/StockTest.php @@ -7,12 +7,7 @@ namespace Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Alerts; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\ObjectManagerInterface; use Magento\Framework\View\LayoutInterface; -use Magento\Store\Model\StoreManagerInterface; -use Magento\TestFramework\Helper\Bootstrap; -use PHPUnit\Framework\TestCase; /** * Check stock alert grid @@ -21,20 +16,11 @@ * * @magentoAppArea adminhtml */ -class StockTest extends TestCase +class StockTest extends AbstractAlertTest { - /** @var ObjectManagerInterface */ - private $objectManager; - /** @var Stock */ private $block; - /** @var StoreManagerInterface */ - private $storeManager; - - /** @var ProductRepositoryInterface */ - private $productRepository; - /** * @inheritdoc */ @@ -42,10 +28,7 @@ protected function setUp(): void { parent::setUp(); - $this->objectManager = Bootstrap::getObjectManager(); $this->block = $this->objectManager->get(LayoutInterface::class)->createBlock(Stock::class); - $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); - $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); } /** @@ -62,9 +45,7 @@ protected function setUp(): void */ public function testGridCollectionWithStoreId(string $sku, string $expectedEmail, ?string $storeCode = null): void { - $productId = (int)$this->productRepository->get($sku)->getId(); - $storeId = $storeCode ? (int)$this->storeManager->getStore($storeCode)->getId() : null; - $this->block->getRequest()->setParams(['id' => $productId, 'store' => $storeId]); + $this->prepareRequest($sku, $storeCode); $collection = $this->block->getPreparedCollection(); $this->assertCount(1, $collection); $this->assertEquals($expectedEmail, $collection->getFirstItem()->getEmail()); @@ -87,4 +68,31 @@ public function alertsDataProvider(): array ], ]; } + + /** + * @dataProvider storeProvider + * + * @param string|null $storeCode + * @return void + */ + public function testGetGridUrl(?string $storeCode): void + { + $this->prepareRequest(null, $storeCode); + $this->assertGridUrl($this->block->getGridUrl(), $storeCode); + } + + /** + * @return array + */ + public function storeProvider(): array + { + return [ + 'without_store_id_param' => [ + 'store_code' => null, + ], + 'with_store_id_param' => [ + 'store_code' => 'default', + ], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AbstractAlertTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AbstractAlertTest.php new file mode 100644 index 0000000000000..5eea3b214435d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AbstractAlertTest.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product; + +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Xpath; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Class contains of base logic for alert controllers tests + */ +abstract class AbstractAlertTest extends AbstractBackendController +{ + /** @var ProductResource */ + private $productResource; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->productResource = $this->_objectManager->get(ProductResource::class); + $this->storeManager = $this->_objectManager->get(StoreManagerInterface::class); + } + + /** + * Prepare request + * + * @param string $productSku + * @param string $storeCode + * @param int|null $limit + * @return void + */ + protected function prepareRequest(string $productSku, string $storeCode, ?int $limit): void + { + $productId = $this->productResource->getIdBySku($productSku); + $storeId = $this->storeManager->getStore($storeCode)->getId(); + $this->getRequest()->setMethod(HttpRequest::METHOD_GET); + $this->getRequest()->setParams(['id' => $productId, 'store' => $storeId, 'limit' => $limit]); + } + + /** + * Assert alert grid records count related to provided email + * + * @param string $email + * @param int $expectedCount + * @return void + */ + protected function assertGridRecords(string $email, int $expectedCount): void + { + $content = $this->getResponse()->getContent(); + $this->assertEquals( + $expectedCount, + Xpath::getElementsCountForXpath(sprintf($this->getRecordXpathTemplate(), $email), $content) + ); + } + + /** + * Get alert grid record xpath template + * + * @return string + */ + abstract protected function getRecordXpathTemplate(): string; +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsPriceGridTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsPriceGridTest.php new file mode 100644 index 0000000000000..f9eafaf2cdc19 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsPriceGridTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product; + +/** + * Tests for price alert grid controller + * + * @see \Magento\Catalog\Controller\Adminhtml\Product\AlertsPriceGrid + * + * @magentoAppArea adminhtml + * @magentoDbIsolation disabled + */ +class AlertsPriceGridTest extends AbstractAlertTest +{ + /** + * @dataProvider priceLimitProvider + * + * @magentoDataFixture Magento/ProductAlert/_files/simple_product_with_two_alerts.php + * + * @param string $email + * @param int|null $limit + * @param $expectedCount + * @return void + */ + public function testExecute(string $email, ?int $limit, $expectedCount): void + { + $this->prepareRequest('simple', 'default', $limit); + $this->dispatch('backend/catalog/product/alertsPriceGrid'); + $this->assertGridRecords($email, $expectedCount); + } + + /** + * @return array + */ + public function priceLimitProvider(): array + { + return [ + 'default_limit' => [ + 'email' => 'customer@example.com', + 'limit' => null, + 'expected_count' => 2, + ], + 'limit_1' => [ + 'email' => 'customer@example.com', + 'limit' => 1, + 'expected_count' => 1, + ], + ]; + } + + /** + * @inheritdoc + */ + protected function getRecordXpathTemplate(): string + { + return "//div[@id='alertPrice']//tbody/tr/td[contains(text(), '%s')]"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsStockGridTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsStockGridTest.php new file mode 100644 index 0000000000000..06e3fbda4c69e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AlertsStockGridTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Product; + +/** + * Tests for stock alert grid controller + * + * @see \Magento\Catalog\Controller\Adminhtml\Product\AlertsStockGrid + * + * @magentoAppArea adminhtml + * @magentoDbIsolation disabled + */ +class AlertsStockGridTest extends AbstractAlertTest +{ + /** + * @dataProvider stockLimitProvider + * + * @magentoDataFixture Magento/ProductAlert/_files/simple_product_with_two_alerts.php + * + * @param string $email + * @param int|null $limit + * @param int $expectedCount + * @return void + */ + public function testExecute(string $email, ?int $limit, int $expectedCount): void + { + $this->prepareRequest('simple', 'default', $limit); + $this->dispatch('backend/catalog/product/alertsStockGrid'); + $this->assertGridRecords($email, $expectedCount); + } + + /** + * @return array + */ + public function stockLimitProvider(): array + { + return [ + 'default_limit' => [ + 'email' => 'customer@example.com', + 'limit' => null, + 'expected_count' => 2, + ], + 'limit_1' => [ + 'email' => 'customer@example.com', + 'limit' => 1, + 'expected_count' => 1, + ], + ]; + } + + /** + * @inheritdoc + */ + protected function getRecordXpathTemplate(): string + { + return "//div[@id='alertStock']//tbody/tr/td[contains(text(), '%s')]"; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php index 96ddc66c875b7..8516916ba8cb3 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AlertsTest.php @@ -40,6 +40,7 @@ protected function setUp(): void /** * @magentoConfigFixture current_store catalog/productalert/allow_stock 1 + * @magentoConfigFixture current_store catalog/productalert/allow_price 1 * * @return void */ @@ -47,10 +48,15 @@ public function testModifyMeta(): void { $meta = $this->stockAlertsModifier->modifyMeta([]); $this->assertArrayHasKey('alerts', $meta); - $content = $meta['alerts']['children'][Alerts::DATA_SCOPE_STOCK]['arguments']['data']['config']['content']; + $stockContent = $meta['alerts']['children'][Alerts::DATA_SCOPE_STOCK]['arguments']['data']['config']['content']; $this->assertEquals( 1, - Xpath::getElementsCountForXpath("//div[@data-grid-id='alertStock']", $content) + Xpath::getElementsCountForXpath("//div[@data-grid-id='alertStock']", $stockContent) + ); + $priceContent = $meta['alerts']['children'][Alerts::DATA_SCOPE_PRICE]['arguments']['data']['config']['content']; + $this->assertEquals( + 1, + Xpath::getElementsCountForXpath("//div[@data-grid-id='alertPrice']", $priceContent) ); } } diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website.php new file mode 100644 index 0000000000000..7bbcbd37bc0e7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\Data\ProductInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\ProductAlert\Model\ResourceModel\Price as PriceResource; +use Magento\ProductAlert\Model\PriceFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var ProductInterfaceFactory $productFactory */ +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PriceFactory $priceFactory */ +$priceFactory = $objectManager->get(PriceFactory::class); +/** @var PriceResource $priceResource */ +$priceResource = $objectManager->get(PriceResource::class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); + + +$product = $productFactory->create(); +$product + ->setTypeId('simple') + ->setAttributeSetId($product->getDefaultAttributeSetId()) + ->setWebsiteIds([(int)$secondWebsite->getId()]) + ->setName('Simple Product2') + ->setSku('simple_on_second_website_for_price_alert') + ->setPrice(10) + ->setMetaTitle('meta title2') + ->setMetaKeyword('meta keyword2') + ->setMetaDescription('meta description2') + ->setVisibility(Visibility::VISIBILITY_BOTH) + ->setStatus(Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]); + +$productRepository->save($product); + +$priceAlert = $priceFactory->create(); +$priceAlert->setCustomerId( + $customer->getId() +)->setProductId( + (int)$productRepository->get($product->getSku())->getId() +)->setWebsiteId( + (int)$secondWebsite->getId() +)->setStoreId( + (int)$storeManager->getStore('fixture_third_store')->getId() +); +$priceResource->save($priceAlert); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website_rollback.php new file mode 100644 index 0000000000000..fce542dca24a1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/price_alert_on_second_website_rollback.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Registry; +use Magento\ProductAlert\Model\ResourceModel\Price as PriceResource; +use Magento\ProductAlert\Model\PriceFactory; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $peoductRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var PriceFactory $priceFactory */ +$priceFactory = $objectManager->get(PriceFactory::class); +/** @var PriceResource $stockResource */ +$stockResource = $objectManager->get(PriceResource::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +$secondWebsite = $storeManager->getWebsite('test'); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer_second_ws_with_addr@example.com', (int)$secondWebsite->getId()); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +try { + $productRepository->deleteById('simple_on_second_website_for_price_alert'); +} catch (NoSuchEntityException $e) { + //already removed +} + + +$priceAlert = $priceFactory->create(); +$priceAlert->deleteCustomer((int)$customer->getId(), (int)$secondWebsite->getId()); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance() + ->requireDataFixture('Magento/Customer/_files/customer_for_second_website_with_address_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php index e9c4900ded341..3db4933f8a12c 100644 --- a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/product_alert_rollback.php @@ -7,6 +7,7 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\Registry; +use Magento\ProductAlert\Model\PriceFactory; use Magento\ProductAlert\Model\StockFactory; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\Workaround\Override\Fixture\Resolver; @@ -14,6 +15,8 @@ $objectManager = Bootstrap::getObjectManager(); /** @var StockFactory $stockFactory */ $stockFactory = $objectManager->get(StockFactory::class); +/** @var PriceFactory $priceFactory */ +$priceFactory = $objectManager->get(PriceFactory::Class); /** @var CustomerRepositoryInterface $customerRepository */ $customerRepository = $objectManager->get(CustomerRepositoryInterface::class); $customer = $customerRepository->get('customer@example.com'); @@ -26,6 +29,9 @@ $stockAlert = $stockFactory->create(); $stockAlert->deleteCustomer((int)$customer->getId()); +$priceAlert = $priceFactory->create(); +$priceAlert->deleteCustomer(($customer->getId())); + $registry->unregister('isSecureArea'); $registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts.php new file mode 100644 index 0000000000000..70f9e2fa97f7f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Customer\Model\CustomerRegistry; +use Magento\ProductAlert\Model\PriceFactory; +use Magento\ProductAlert\Model\ResourceModel\Price as PriceResource; +use Magento\ProductAlert\Model\ResourceModel\Stock as StockResource; +use Magento\ProductAlert\Model\StockFactory; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer.php'); +Resolver::getInstance()->requireDataFixture('Magento/ProductAlert/_files/product_alert.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +$product = $productRepository->get('simple'); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +$baseWebsiteId = (int)$websiteRepository->get('base')->getId(); +/** @var CustomerRegistry $customerRegistry */ +$customerRegistry = $objectManager->create(CustomerRegistry::class); +$customer = $customerRegistry->retrieve(1); +/** @var PriceFactory $priceFactory */ +$priceFactory = $objectManager->get(PriceFactory::class); +/** @var PriceResource $priceResource */ +$priceResource = $objectManager->get(PriceResource::class); +$priceAlert = $priceFactory->create(); +$priceAlert->setCustomerId( + $customer->getId() +)->setProductId( + $product->getId() +)->setPrice( + $product->getPrice()+1 +)->setWebsiteId( + $baseWebsiteId +); +$priceResource->save($priceAlert); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var StockResource $stockResource */ +$stockResource = $objectManager->get(StockResource::class); +$stockAlert = $stockFactory->create(); +$stockAlert->setCustomerId( + $customer->getId() +)->setProductId( + $product->getId() +)->setWebsiteId( + $baseWebsiteId +); +$stockResource->save($stockAlert); diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts_rollback.php b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts_rollback.php new file mode 100644 index 0000000000000..93614e974931d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/_files/simple_product_with_two_alerts_rollback.php @@ -0,0 +1,39 @@ +<?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\Registry; +use Magento\ProductAlert\Model\PriceFactory; +use Magento\ProductAlert\Model\StockFactory; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +$objectManager = Bootstrap::getObjectManager(); +/** @var StockFactory $stockFactory */ +$stockFactory = $objectManager->get(StockFactory::class); +/** @var PriceFactory $priceFactory */ +$priceFactory = $objectManager->get(PriceFactory::Class); +/** @var CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->get(CustomerRepositoryInterface::class); +$customer = $customerRepository->get('customer@example.com'); +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +$stockAlert = $stockFactory->create(); +$stockAlert->deleteCustomer((int)$customer->getId()); + +$priceAlert = $priceFactory->create(); +$priceAlert->deleteCustomer(($customer->getId())); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/ProductAlert/_files/product_alert_rollback.php'); From 5a92ebf39a5fdf290107e69383fb74efd9fa7423 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Mon, 18 Jan 2021 12:28:28 +0200 Subject: [PATCH 223/242] MC-39584: Create automated test for: "Switching store views of category" --- .../Adminhtml/Category/EditTest.php | 75 +++++++++++++++++++ .../Catalog/_files/second_root_category.php | 21 ++++++ .../_files/second_root_category_rollback.php | 37 +++++++++ 3 files changed, 133 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php new file mode 100644 index 0000000000000..3c3dc26464d1e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Controller\Adminhtml\Category; + +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Model\ResourceModel\Category\Collection; +use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\TestCase\AbstractBackendController; + +/** + * Test cases related to edit category. + * + * @see \Magento\Catalog\Controller\Adminhtml\Category\Edit + * @magentoAppArea adminhtml + * @magentoDbIsolation enabled + */ +class EditTest extends AbstractBackendController +{ + /** @var Collection */ + private $categoryCollectionFactory; + + /** @var StoreManagerInterface */ + private $storeManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->categoryCollectionFactory = $this->_objectManager->get(CollectionFactory::class); + $this->storeManager = $this->_objectManager->get(StoreManagerInterface::class); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_root_category.php + * + * @return void + */ + public function testSwitchingStoreViewsCategory(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_GET); + $id = (int)$this->getCategoryIdByName('Second Root Category'); + $storeId = (int)$this->storeManager->getStore('default')->getId(); + $this->getRequest()->setParams(['store' => $storeId, 'id' => $id]); + $this->dispatch('backend/catalog/category/edit'); + $this->assertRedirect($this->stringContains('backend/catalog/category/index')); + $this->assertStringNotContainsString('/id/', $this->getResponse()->getHeader('Location')->getFieldValue()); + } + + /** + * Get category id by name + * + * @param string $name + * @return string|null + */ + private function getCategoryIdByName(string $name): ?string + { + $categoryCollection = $this->categoryCollectionFactory->create(); + $category = $categoryCollection + ->addAttributeToFilter(CategoryInterface::KEY_NAME, $name) + ->setPageSize(1) + ->getFirstItem(); + + return $category->getId(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php new file mode 100644 index 0000000000000..fec1be2fe5d3e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\CategoryFactory; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CategoryFactory $categoryFactory */ +$categoryFactory = $objectManager->get(CategoryFactory::class); +$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class); +$rootCategory = $categoryFactory->create(); +$rootCategory->setName('Second Root Category') + ->setParentId(Category::TREE_ROOT_ID) + ->setIsActive(true); +$rootCategory = $categoryRepository->save($rootCategory); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php new file mode 100644 index 0000000000000..f6d347988c526 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Model\CategoryRepository; +use Magento\Catalog\Model\ResourceModel\Category\Collection; +use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; +use Magento\Framework\Registry; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var CategoryRepository $categoryRepository */ +$categoryRepository = $objectManager->create(CategoryRepositoryInterface::class); +/** @var CollectionFactory $categoryCollectionFactory */ +$categoryCollectionFactory = $objectManager->get(CollectionFactory::class); + +/** @var Registry $registry */ +$registry = $objectManager->get(Registry::class); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var Collection $categoryCollection */ +$categoryCollection = $categoryCollectionFactory->get(); +$category = $categoryCollection + ->addAttributeToFilter(CategoryInterface::KEY_NAME, 'Second Root Category') + ->setPageSize(1) + ->getFirstItem(); +if ($category->getId()) { + $categoryRepository->delete($category); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); From f0f201cc7ac0bdce843ad31cf798294f2d0696e9 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Mon, 18 Jan 2021 15:43:38 +0200 Subject: [PATCH 224/242] MC-38088: [MFTF] Flaky AdminSimpleProductRemoveImagesTest --- .../ActionGroup/AdminOpenProductImagesSectionActionGroup.xml | 3 ++- .../AdminSimpleProductRemoveImagesTest.xml | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml index 407cc339de501..fc965dcfc629a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenProductImagesSectionActionGroup.xml @@ -12,8 +12,9 @@ <annotations> <description>Requires the navigation to the Product page. Opens 'Image and Videos' section.</description> </annotations> - <scrollTo selector="{{AdminProductImagesSection.productImagesToggle}}" stepKey="scrollToProductImagesTab"/> <conditionalClick selector="{{AdminProductImagesSection.productImagesToggle}}" dependentSelector="{{AdminProductImagesSection.imageUploadButton}}" visible="false" stepKey="openProductImagesSection"/> + <scrollTo selector="{{AdminProductImagesSection.productImagesToggle}}" stepKey="scrollToProductImagesSection"/> + <waitForPageLoad stepKey="waitForLoadingMediaContent"/> <waitForElementVisible selector="{{AdminProductImagesSection.imageUploadButton}}" stepKey="waitForImageUploadButton"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml index bb6a3417e7b74..9dae1259cc4f9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminSimpleProductImagesTest/AdminSimpleProductRemoveImagesTest.xml @@ -49,7 +49,6 @@ <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages"/> <!-- Upload and set Base image --> - <waitForPageLoad stepKey="waitBeforeAttachImages"/> <attachFile selector="{{AdminProductImagesSection.imageFileUpload}}" userInput="adobe-base.jpg" stepKey="attach1"/> <waitForPageLoad stepKey="waitForUpload1"/> <click selector="{{AdminProductImagesSection.nthProductImage('1')}}" stepKey="openImageDetails1"/> @@ -116,7 +115,7 @@ <actionGroup ref="AdminOpenProductImagesSectionActionGroup" stepKey="expandImages2"/> <!-- Remove all images --> - <waitForPageLoad stepKey="waitBeforeRemoveImages"/> + <waitForElementVisible selector="{{AdminProductImagesSection.nthRemoveImageBtn('1')}}" stepKey="waitForRemoveImageButtonVisible"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('1')}}" stepKey="removeImage1"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('2')}}" stepKey="removeImage2"/> <click selector="{{AdminProductImagesSection.nthRemoveImageBtn('3')}}" stepKey="removeImage3"/> From 52e04e64df08ddd5c939f82f4d6aefde83d3a9e6 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Mon, 18 Jan 2021 16:43:32 +0200 Subject: [PATCH 225/242] MC-40376: Auto suggestion box not reappearing after clicking outside the text field --- app/code/Magento/Search/view/frontend/web/js/form-mini.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Search/view/frontend/web/js/form-mini.js b/app/code/Magento/Search/view/frontend/web/js/form-mini.js index b8034fead76d0..df651feb89d45 100644 --- a/app/code/Magento/Search/view/frontend/web/js/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/js/form-mini.js @@ -253,6 +253,8 @@ define([ } this.element.val(this.responseList.selected.find('.qs-option-name').text()); this.element.attr('aria-activedescendant', this.responseList.selected.attr('id')); + this._updateAriaHasPopup(true); + this.autoComplete.show(); } break; @@ -269,6 +271,8 @@ define([ } this.element.val(this.responseList.selected.find('.qs-option-name').text()); this.element.attr('aria-activedescendant', this.responseList.selected.attr('id')); + this._updateAriaHasPopup(true); + this.autoComplete.show(); } break; default: From 77e1e2beacbcd03da2fe612ccfdb6c0c23e00951 Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Mon, 18 Jan 2021 17:23:44 +0200 Subject: [PATCH 226/242] MC-40384: [Magento Cloud] Order Grid created time showing wrong --- .../ResourceModel/Order/Grid/Collection.php | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php index 82c612c1a781d..094fac313d398 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Grid/Collection.php @@ -5,16 +5,25 @@ */ namespace Magento\Sales\Model\ResourceModel\Order\Grid; +use Magento\Framework\App\ObjectManager; 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\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult; +use Magento\Sales\Model\ResourceModel\Order; use Psr\Log\LoggerInterface as Logger; /** * Order grid collection */ -class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +class Collection extends SearchResult { + /** + * @var TimezoneInterface + */ + private $timeZone; + /** * Initialize dependencies. * @@ -24,6 +33,7 @@ class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvide * @param EventManager $eventManager * @param string $mainTable * @param string $resourceModel + * @param TimezoneInterface|null $timeZone */ public function __construct( EntityFactory $entityFactory, @@ -31,9 +41,12 @@ public function __construct( FetchStrategy $fetchStrategy, EventManager $eventManager, $mainTable = 'sales_order_grid', - $resourceModel = \Magento\Sales\Model\ResourceModel\Order::class + $resourceModel = Order::class, + TimezoneInterface $timeZone = null ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + $this->timeZone = $timeZone ?: ObjectManager::getInstance() + ->get(TimezoneInterface::class); } /** @@ -50,4 +63,20 @@ protected function _initSelect() return $this; } + + /** + * @inheritDoc + */ + public function addFieldToFilter($field, $condition = null) + { + if ($field === 'created_at') { + if (is_array($condition)) { + foreach ($condition as $key => $value) { + $condition[$key] = $this->timeZone->convertConfigTimeToUtc($value); + } + } + } + + return parent::addFieldToFilter($field, $condition); + } } From dfb79dc044c6e57b0d035adf51fa206813d3e120 Mon Sep 17 00:00:00 2001 From: Serhii Bohomaz <serhii.bohomaz@transoftgroup.com> Date: Mon, 18 Jan 2021 18:44:16 +0200 Subject: [PATCH 227/242] MC-39584: Create automated test for: "Switching store views of category" --- .../Adminhtml/Category/EditTest.php | 3 +- .../Category/Save/SaveCategoryTest.php | 38 +++++++++++++++++++ .../Catalog/_files/second_root_category.php | 3 +- .../_files/second_root_category_rollback.php | 9 ++--- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php index 3c3dc26464d1e..f8a22ad05172c 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/EditTest.php @@ -8,7 +8,6 @@ namespace Magento\Catalog\Controller\Adminhtml\Category; use Magento\Catalog\Api\Data\CategoryInterface; -use Magento\Catalog\Model\ResourceModel\Category\Collection; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\Framework\App\Request\Http as HttpRequest; use Magento\Store\Model\StoreManagerInterface; @@ -23,7 +22,7 @@ */ class EditTest extends AbstractBackendController { - /** @var Collection */ + /** @var CollectionFactory */ private $categoryCollectionFactory; /** @var StoreManagerInterface */ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php index 3a93161517301..7e921b5c7ac12 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Category/Save/SaveCategoryTest.php @@ -15,6 +15,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Message\MessageInterface; use Magento\Store\Model\StoreManagerInterface; +use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; /** * Test cases for save category controller. @@ -36,6 +37,9 @@ class SaveCategoryTest extends AbstractSaveCategoryTest /** @var StoreManagerInterface */ private $storeManager; + /** @var CollectionFactory */ + private $categoryCollectionFactory; + /** * @inheritdoc */ @@ -46,6 +50,7 @@ protected function setUp(): void $this->categoryRepository = $this->_objectManager->get(CategoryRepositoryInterface::class); $this->getBlockByIdentifier = $this->_objectManager->get(GetBlockByIdentifierInterface::class); $this->storeManager = $this->_objectManager->get(StoreManagerInterface::class); + $this->categoryCollectionFactory = $this->_objectManager->get(CollectionFactory::class); } /** @@ -109,4 +114,37 @@ public function testTryToCreateCategoryWithEmptyValues(): void ); $this->assertSessionMessages($this->containsEqual($message), MessageInterface::TYPE_ERROR); } + + /** + * @magentoDataFixture Magento/Catalog/_files/second_root_category.php + * + * @return void + */ + public function testSwitchingStoreViewsCategory(): void + { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); + $id = (int)$this->getCategoryIdByName('Second Root Category'); + $storeId = (int)$this->storeManager->getStore('default')->getId(); + $this->getRequest()->setParams(['store' => $storeId, 'id' => $id]); + $this->dispatch('backend/catalog/category/save'); + $this->assertRedirect($this->stringContains('backend/catalog/category/index')); + $this->assertStringNotContainsString('/id/', $this->getResponse()->getHeader('Location')->getFieldValue()); + } + + /** + * Get category id by name + * + * @param string $name + * @return string|null + */ + private function getCategoryIdByName(string $name): ?string + { + $categoryCollection = $this->categoryCollectionFactory->create(); + $category = $categoryCollection + ->addAttributeToFilter(CategoryInterface::KEY_NAME, $name) + ->setPageSize(1) + ->getFirstItem(); + + return $category->getId(); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php index fec1be2fe5d3e..7a38cd6eeb52c 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category.php @@ -13,9 +13,10 @@ $objectManager = Bootstrap::getObjectManager(); /** @var CategoryFactory $categoryFactory */ $categoryFactory = $objectManager->get(CategoryFactory::class); +/** @var CategoryRepositoryInterface $categoryRepository */ $categoryRepository = $objectManager->get(CategoryRepositoryInterface::class); $rootCategory = $categoryFactory->create(); $rootCategory->setName('Second Root Category') ->setParentId(Category::TREE_ROOT_ID) ->setIsActive(true); -$rootCategory = $categoryRepository->save($rootCategory); +$categoryRepository->save($rootCategory); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php index f6d347988c526..142ebf5412c10 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/second_root_category_rollback.php @@ -7,15 +7,13 @@ use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryInterface; -use Magento\Catalog\Model\CategoryRepository; -use Magento\Catalog\Model\ResourceModel\Category\Collection; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\Framework\Registry; use Magento\TestFramework\Helper\Bootstrap; $objectManager = Bootstrap::getObjectManager(); -/** @var CategoryRepository $categoryRepository */ -$categoryRepository = $objectManager->create(CategoryRepositoryInterface::class); +/** @var CategoryRepositoryInterface $categoryRepository */ +$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class); /** @var CollectionFactory $categoryCollectionFactory */ $categoryCollectionFactory = $objectManager->get(CollectionFactory::class); @@ -23,8 +21,7 @@ $registry = $objectManager->get(Registry::class); $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); -/** @var Collection $categoryCollection */ -$categoryCollection = $categoryCollectionFactory->get(); +$categoryCollection = $categoryCollectionFactory->create(); $category = $categoryCollection ->addAttributeToFilter(CategoryInterface::KEY_NAME, 'Second Root Category') ->setPageSize(1) From 94987c015acc4898e1a5612d369661234c5497aa Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 19 Jan 2021 10:35:53 +0200 Subject: [PATCH 228/242] MC-40376: Auto suggestion box not reappearing after clicking outside the text field --- ...ertDropDownSearchSuggestionActionGroup.xml | 29 +++++++++ ...fySearchSuggestionByControlButtonsTest.xml | 65 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml create mode 100644 app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml new file mode 100644 index 0000000000000..62cb3ac70cbc4 --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml @@ -0,0 +1,29 @@ +<?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="StoreFrontAssertDropDownSearchSuggestionActionGroup"> + <annotations> + <description>Fills the Storefront Quick Search field. Validates that the Search Suggestion is present</description> + </annotations> + <arguments> + <argument name="searchQuery" type="string"/> + </arguments> + + <waitForElementVisible selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" stepKey="waitForQuickSearchToBeVisible"/> + <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{searchQuery}}" stepKey="fillSearchInput"/> + <waitForElementVisible selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="WaitForSearchDropDownSuggestion"/> + <see selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="seeDropDownSuggestion"/> + <click selector="//div[@class='panel wrapper']" stepKey="clickOnSomewhere"/> + <dontSee selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="dontSeeDropDownSuggestion"/> + <click selector="{{StorefrontQuickSearchSection.searchPhrase}}" stepKey="clickOnSearchPhrase"/> + <pressKey selector="{{StorefrontQuickSearchSection.searchPhrase}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::DOWN]" stepKey="pressDown"/> + <see selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="seeDropDownSuggestionSecond"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml new file mode 100644 index 0000000000000..e325ecd1fe3ae --- /dev/null +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontVerifySearchSuggestionByControlButtonsTest"> + <annotations> + <stories value="Search Term"/> + <title value="Auto suggestion box not reappearing after clicking outside the text field"/> + <description value="Auto suggestion box not reappearing after clicking outside the text field"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-40466"/> + <useCaseId value="MC-40376"/> + </annotations> + + <before> + <!-- Login as admin --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + + <!-- Create Simple Product --> + <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + + <!-- Perform reindex and flush cache --> + <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> + <argument name="indices" value=""/> + </actionGroup> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCache"> + <argument name="tags" value=""/> + </actionGroup> + </before> + <after> + <!-- Delete create product --> + <deleteData createDataKey="simpleProduct" stepKey="deleteProduct"/> + + <!-- Go to the catalog search term page --> + <actionGroup ref="AdminOpenCatalogSearchTermIndexPageActionGroup" stepKey="openAdminCatalogSearchTermIndexPage"/> + + <!-- Filter the search term --> + <actionGroup ref="AdminSearchTermFilterBySearchQueryActionGroup" stepKey="filterByThirdSearchQuery"> + <argument name="searchQuery" value="$$simpleProduct.name$$"/> + </actionGroup> + <!-- Delete created below search terms --> + <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!-- Go to storefront home page --> + <actionGroup ref="StorefrontOpenHomePageActionGroup" stepKey="openStoreFrontHomePage"/> + + <!-- Storefront quick search by product name --> + <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> + <argument name="phrase" value="$$simpleProduct.name$$"/> + </actionGroup> + + <!-- Verify search suggestions and select the suggestion from dropdown options --> + <actionGroup ref="StoreFrontAssertDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> + <argument name="searchQuery" value="$$simpleProduct.name$$"/> + </actionGroup> + </test> +</tests> From 609d9059436071448f493f54784b944c55502c30 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 19 Jan 2021 12:27:32 +0200 Subject: [PATCH 229/242] MC-39550: Create automated test for: "Add new website to products using mass product update and run cron." --- .../Backend/ConsumerWebsiteAssignTest.php | 262 ++++++++++++++++++ .../detach_product_website_quene_data.php | 62 +++++ ...ch_product_website_quene_data_rollback.php | 17 ++ .../update_product_website_quene_data.php | 63 +++++ ...te_product_website_quene_data_rollback.php | 18 ++ 5 files changed, 422 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data_rollback.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php new file mode 100644 index 0000000000000..e895a886e44e7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php @@ -0,0 +1,262 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Model\Attribute\Backend; + +use Magento\AsynchronousOperations\Api\Data\OperationInterface as OperationDataInterface; +use Magento\AsynchronousOperations\Model\ResourceModel\Operation\CollectionFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Catalog\Model\Product\Action; +use Magento\Framework\Bulk\OperationInterface; +use Magento\Framework\DB\Adapter\DeadlockException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\MessageQueue\MessageEncoder; +use Magento\Framework\ObjectManagerInterface; +use Magento\MysqlMq\Model\Driver\Queue; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\MysqlMq\DeleteTopicRelatedMessages; +use PHPUnit\Framework\TestCase; + +/** + * Tests for Mysql website assigning consumer + * + * @see \Magento\Catalog\Model\Attribute\Backend\ConsumerWebsiteAssign + * + * @magentoDbIsolation disabled + * @magentoAppArea adminhtml + */ +class ConsumerWebsiteAssignTest extends TestCase +{ + private const TOPIC_NAME = 'product_action_attribute.website.update'; + + /** @var DeleteTopicRelatedMessages */ + private static $deleteTopicRelatedMessages; + + /** @var ObjectManagerInterface */ + private $objectManager; + + /** @var ConsumerWebsiteAssign */ + private $consumer; + + /** @var Queue */ + private $queue; + + /** @var MessageEncoder */ + private $messageEncoder; + + /** @var ProductRepositoryInterface */ + private $productRepository; + + /** @var WebsiteRepositoryInterface */ + private $websiteRepository; + + /** @var CollectionFactory */ + private $operationCollectionFactory; + + /** + * @inheritdoc + */ + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + + $objectManager = Bootstrap::getObjectManager(); + self::$deleteTopicRelatedMessages = $objectManager->get(DeleteTopicRelatedMessages::class); + self::$deleteTopicRelatedMessages->execute(self::TOPIC_NAME); + } + + /** + * @inheritdoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->objectManager = Bootstrap::getObjectManager(); + $this->consumer = $this->objectManager->get(ConsumerWebsiteAssign::class); + $this->queue = $this->objectManager->create( + Queue::class, + ['queueName' => 'product_action_attribute.website.update'] + ); + $this->messageEncoder = $this->objectManager->get(MessageEncoder::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class); + $this->operationCollectionFactory = $this->objectManager->get(CollectionFactory::class); + } + + /** + * @return void + */ + protected function tearDown(): void + { + $this->objectManager->removeSharedInstance(Action::class); + self::$deleteTopicRelatedMessages->execute(self::TOPIC_NAME); + + parent::tearDown(); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/update_product_website_quene_data.php + * + * @return void + */ + public function testAddWebsite(): void + { + $this->processMessages(); + $this->assertProductWebsites('simple2', ['base', 'test']); + $this->assertOperation(OperationInterface::STATUS_TYPE_COMPLETE); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/detach_product_website_quene_data.php + * + * @return void + */ + public function testRemoveWebsite(): void + { + $this->processMessages(); + $this->assertProductWebsites('unique-simple-azaza', ['base']); + $this->assertOperation(OperationInterface::STATUS_TYPE_COMPLETE); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/update_product_website_quene_data.php + * + * @return void + */ + public function testAddWebsiteToDeletedProduct(): void + { + $expectedMessage = __('Something went wrong while adding products to websites.'); + $this->productRepository->deleteById('simple2'); + $this->processMessages(); + $this->assertOperation(OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, (string)$expectedMessage); + } + + /** + * @dataProvider errorProvider + * + * @magentoDataFixture Magento/Catalog/_files/update_product_website_quene_data.php + * + * @param \Throwable $exception + * @param int $code + * @return void + */ + public function testWithException(\Throwable $exception, int $code): void + { + $this->prepareMock($exception); + $this->processMessages(); + $this->assertOperation($code, $exception->getMessage()); + } + + /** + * @return array + */ + public function errorProvider(): array + { + return [ + 'with_dead_lock_exception' => [ + 'exception' => new DeadlockException('Test lock'), + 'code' => OperationDataInterface::STATUS_TYPE_RETRIABLY_FAILED, + ], + 'with_db_exception' => [ + 'exception' => new \Zend_Db_Adapter_Exception( + (string)__( + 'Sorry, something went wrong during product attributes update. Please see log for details.' + ) + ), + 'code' => OperationDataInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, + ], + 'with_no_such_entity_exception' => [ + 'exception' => new NoSuchEntityException(), + 'code' => OperationDataInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, + ], + 'with_general_exception' => [ + 'exception' => new \Exception( + (string)__( + 'Sorry, something went wrong during product attributes update. Please see log for details.' + ) + ), + 'code' => OperationDataInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, + ], + ]; + } + + /** + * Assert product website ids + * + * @param string $sku + * @param array $expectedWebsites + * @return void + */ + private function assertProductWebsites(string $sku, array $expectedWebsites): void + { + $product = $this->productRepository->get($sku, false, null, true); + $websitesIds = $product->getWebsiteIds(); + $this->assertCount(count($expectedWebsites), $websitesIds); + + foreach ($expectedWebsites as $expectedWebsite) { + $expectedWebsiteId = $this->websiteRepository->get($expectedWebsite)->getId(); + $this->assertContains($expectedWebsiteId, $websitesIds); + } + } + + /** + * Process current consumer topic messages + * + * @return void + */ + private function processMessages(): void + { + $envelope = $this->queue->dequeue(); + $decodedMessage = $this->messageEncoder->decode(self::TOPIC_NAME, $envelope->getBody()); + $this->consumer->process($decodedMessage); + } + + /** + * Get last current topic related operation + * + * @return OperationDataInterface + */ + private function getLastTopicOperation(): OperationDataInterface + { + $collection = $this->operationCollectionFactory->create(); + $collection->addFieldToFilter('topic_name', self::TOPIC_NAME); + $collection->setPageSize(1)->setCurPage($collection->getLastPageNumber()); + + return $collection->getLastItem(); + } + + /** + * Assert performed operation + * + * @param int $status + * @param string|null $resultMessage + * @return void + */ + private function assertOperation(int $status, ?string $resultMessage = null): void + { + $operation = $this->getLastTopicOperation(); + $this->assertNotNull($operation->getData('id')); + $this->assertEquals($status, $operation->getStatus()); + $this->assertEquals($resultMessage, $operation->getResultMessage()); + } + + /** + * Create mock with provided exception + * + * @param \Throwable $exception + * @return void + */ + private function prepareMock(\Throwable $exception): void + { + $object = $this->createPartialMock(Action::class, ['updateWebsites']); + $object->method('updateWebsites')->willThrowException($exception); + $this->objectManager->addSharedInstance($object, Action::class); + $this->consumer = $this->objectManager->create(ConsumerWebsiteAssign::class); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php new file mode 100644 index 0000000000000..ab03ff5bf6b65 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\AsynchronousOperations\Api\Data\OperationInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Bulk\BulkManagementInterface; +use Magento\Framework\Bulk\OperationInterface; +use Magento\Framework\DataObject\IdentityGeneratorInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_with_two_websites.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var IdentityGeneratorInterface $identityService */ +$identityService = $objectManager->get(IdentityGeneratorInterface::class); +/** @var SerializerInterface $jsonEncoder */ +$jsonEncoder = $objectManager->get(SerializerInterface::class); +/** @var OperationInterfaceFactory $optionFactory */ +$optionFactory = $objectManager->get(OperationInterfaceFactory::class); +/** @var BulkManagementInterface $bulkManagement */ +$bulkManagement = $objectManager->get(BulkManagementInterface::class); +$productIds = [(int)$productRepository->get('unique-simple-azaza')->getId()]; +$websiteId = (int)$websiteRepository->get('second_website')->getId(); +$bulkDescription = __('Update attributes for ' . 1 . ' selected products'); +$dataToEncode = [ + 'meta_information' => 'Update website assign', + 'product_ids' => $productIds, + 'store_id' => 0, + 'website_id' => $websiteId, + 'attributes' => [ + 'website_assign' => [], + 'website_detach' => [$websiteId], + ], +]; +$bulkUid = $identityService->generateId(); +$data = [ + 'data' => [ + 'bulk_uuid' => $bulkUid, + 'topic_name' => 'product_action_attribute.website.update', + 'serialized_data' => $jsonEncoder->serialize($dataToEncode), + 'status' => OperationInterface::STATUS_TYPE_OPEN, + ] +]; + +$bulkManagement->scheduleBulk( + $bulkUid, + [$optionFactory->create($data)], + $bulkDescription, + 1 +); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data_rollback.php new file mode 100644 index 0000000000000..df62ecc22c623 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data_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\MysqlMq\DeleteTopicRelatedMessages; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +$objectManager = Bootstrap::getObjectManager(); +/** @var DeleteTopicRelatedMessages $deleteTopicRelatedMessages */ +$deleteTopicRelatedMessages = $objectManager->get(DeleteTopicRelatedMessages::class); +$deleteTopicRelatedMessages->execute('product_action_attribute.website.update'); + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_with_two_websites_rollback.php'); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php new file mode 100644 index 0000000000000..dca8fb26c0b55 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\AsynchronousOperations\Api\Data\OperationInterfaceFactory; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Bulk\BulkManagementInterface; +use Magento\Framework\Bulk\OperationInterface; +use Magento\Framework\DataObject\IdentityGeneratorInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Store\Api\WebsiteRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +Resolver::getInstance()->requireDataFixture('Magento/Store/_files/second_website_with_two_stores.php'); +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/second_product_simple.php'); + +$objectManager = Bootstrap::getObjectManager(); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->get(ProductRepositoryInterface::class); +$productRepository->cleanCache(); +/** @var WebsiteRepositoryInterface $websiteRepository */ +$websiteRepository = $objectManager->get(WebsiteRepositoryInterface::class); +/** @var IdentityGeneratorInterface $identityService */ +$identityService = $objectManager->get(IdentityGeneratorInterface::class); +/** @var SerializerInterface $jsonEncoder */ +$jsonEncoder = $objectManager->get(SerializerInterface::class); +/** @var OperationInterfaceFactory $optionFactory */ +$optionFactory = $objectManager->get(OperationInterfaceFactory::class); +/** @var BulkManagementInterface $bulkManagement */ +$bulkManagement = $objectManager->get(BulkManagementInterface::class); +$productIds = [(int)$productRepository->get('simple2')->getId()]; +$websiteId = (int)$websiteRepository->get('test')->getId(); +$bulkDescription = __('Update attributes for ' . 1 . ' selected products'); +$dataToEncode = [ + 'meta_information' => 'Update website assign', + 'product_ids' => $productIds, + 'store_id' => 0, + 'website_id' => $websiteId, + 'attributes' => [ + 'website_assign' => [$websiteId], + 'website_detach' => [], + ], +]; +$bulkUid = $identityService->generateId(); +$data = [ + 'data' => [ + 'bulk_uuid' => $bulkUid, + 'topic_name' => 'product_action_attribute.website.update', + 'serialized_data' => $jsonEncoder->serialize($dataToEncode), + 'status' => OperationInterface::STATUS_TYPE_OPEN, + ] +]; + +$bulkManagement->scheduleBulk( + $bulkUid, + [$optionFactory->create($data)], + $bulkDescription, + 1 +); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php new file mode 100644 index 0000000000000..5273947cd28ea --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_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\TestFramework\MysqlMq\DeleteTopicRelatedMessages; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Workaround\Override\Fixture\Resolver; + +$objectManager = Bootstrap::getObjectManager(); +/** @var DeleteTopicRelatedMessages $deleteTopicRelatedMessages */ +$deleteTopicRelatedMessages = $objectManager->get(DeleteTopicRelatedMessages::class); +$deleteTopicRelatedMessages->execute('product_action_attribute.website.update'); + +Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/second_product_simple_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Store/_files/second_website_with_store_group_and_store_rollback.php'); From 6a27b0ce155a418e05bf6a7753af5a947af5668e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Tue, 19 Jan 2021 13:34:57 +0200 Subject: [PATCH 230/242] MC-39481: MAGENTO 2.3.5 /V1/products overwrite default values on multi-store site even when only one field is sent to update --- .../Catalog/Model/ProductRepository.php | 44 +++- .../Test/Unit/Model/ProductRepositoryTest.php | 6 +- .../Api/ProductRepositoryMultiWebsiteTest.php | 196 ++++++++++++++++++ 3 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryMultiWebsiteTest.php diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index fefeafe46e1c4..2d60756c9e331 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -28,6 +28,8 @@ use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\TemporaryState\CouldNotSaveException as TemporaryCouldNotSaveException; use Magento\Framework\Exception\ValidatorException; +use Magento\Store\Model\Store; +use Magento\Catalog\Api\Data\EavAttributeInterface; /** * @inheritdoc @@ -514,9 +516,12 @@ public function save(ProductInterface $product, $saveOptions = false) { $assignToCategories = false; $tierPrices = $product->getData('tier_price'); + $productDataToChange = $product->getData(); try { - $existingProduct = $product->getId() ? $this->getById($product->getId()) : $this->get($product->getSku()); + $existingProduct = $product->getId() ? + $this->getById($product->getId()) : + $this->get($product->getSku()); $product->setData( $this->resourceModel->getLinkField(), @@ -548,7 +553,6 @@ public function save(ProductInterface $product, $saveOptions = false) $productDataArray['store_id'] = (int) $this->storeManager->getStore()->getId(); } $product = $this->initializeProductData($productDataArray, empty($existingProduct)); - $this->processLinks($product, $productLinks); if (isset($productDataArray['media_gallery'])) { $this->processMediaGallery($product, $productDataArray['media_gallery']['images']); @@ -569,6 +573,42 @@ public function save(ProductInterface $product, $saveOptions = false) $product->setData('tier_price', $tierPrices); } + try { + $stores = $product->getStoreIds(); + $websites = $product->getWebsiteIds(); + } catch (NoSuchEntityException $exception) { + $stores = null; + $websites = null; + } + + if (!empty($existingProduct) && is_array($stores) && is_array($websites)) { + $hasDataChanged = false; + $productAttributes = $product->getAttributes(); + if ($productAttributes !== null + && $product->getStoreId() !== Store::DEFAULT_STORE_ID + && (count($stores) > 1 || count($websites) === 1) + ) { + foreach ($productAttributes as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + $value = $product->getData($attributeCode); + if ($existingProduct->getData($attributeCode) === $value + && $attribute->getScope() !== EavAttributeInterface::SCOPE_GLOBAL_TEXT + && !is_array($value) + && $attribute->getData('frontend_input') !== 'media_image' + && !$attribute->isStatic() + && !array_key_exists($attributeCode, $productDataToChange) + && $value !== null + ) { + $product->setData($attributeCode); + $hasDataChanged = true; + } + } + if ($hasDataChanged) { + $product->setData('_edit_mode', true); + } + } + } + $this->saveProduct($product); if ($assignToCategories === true && $product->getCategoryIds()) { $this->linkManagement->assignProductToCategories( diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php index 129873a067d97..3b7b4b8734f04 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php @@ -220,7 +220,8 @@ protected function setUp(): void 'getStoreId', 'getMediaGalleryEntries', 'getExtensionAttributes', - 'getCategoryIds' + 'getCategoryIds', + 'getAttributes' ] ) ->disableOriginalConstructor() @@ -243,7 +244,8 @@ protected function setUp(): void 'save', 'getMediaGalleryEntries', 'getExtensionAttributes', - 'getCategoryIds' + 'getCategoryIds', + 'getAttributes' ] ) ->disableOriginalConstructor() diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryMultiWebsiteTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryMultiWebsiteTest.php new file mode 100644 index 0000000000000..9c8ca40a0c8f3 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryMultiWebsiteTest.php @@ -0,0 +1,196 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Catalog\Api; + +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Store\Model\Store; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; +use Magento\Catalog\Model\Attribute\ScopeOverriddenValue; +use Magento\Catalog\Model\Product; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Framework\ObjectManagerInterface; + +/** + * Test for \Magento\Catalog\Api\ProductRepositoryInterface + * + * @magentoAppIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + */ +class ProductRepositoryMultiWebsiteTest extends WebapiAbstract +{ + const SERVICE_NAME = 'catalogProductRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/products'; + + /** + * @var array + */ + private $fixtureProducts = []; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * @inheritDoc + */ + protected function tearDown(): void + { + parent::tearDown(); + $this->deleteFixtureProducts(); + } + + /** + * Save Product + * + * @param array $product + * @param string|null $storeCode + * @param string|null $token + * @return mixed + */ + private function saveProduct(array $product, ?string $storeCode = null, ?string $token = null) + { + if (isset($product['custom_attributes'])) { + foreach ($product['custom_attributes'] as &$attribute) { + if ($attribute['attribute_code'] == 'category_ids' + && !is_array($attribute['value']) + ) { + $attribute['value'] = [""]; + } + } + } + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + if ($token) { + $serviceInfo['rest']['token'] = $serviceInfo['soap']['token'] = $token; + } + $requestData = ['product' => $product]; + + return $this->_webApiCall($serviceInfo, $requestData, null, $storeCode); + } + + /** + * Delete Product + * + * @param string $sku + * @return boolean + */ + private function deleteProduct(string $sku) : bool + { + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $sku, + 'httpMethod' => Request::HTTP_METHOD_DELETE, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'DeleteById', + ], + ]; + + return (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) ? + $this->_webApiCall($serviceInfo, ['sku' => $sku]) : $this->_webApiCall($serviceInfo); + } + + /** + * @return void + */ + private function deleteFixtureProducts(): void + { + foreach ($this->fixtureProducts as $sku) { + $this->deleteProduct($sku); + } + $this->fixtureProducts = []; + } + + /** + * Test that updating some values for product for specified store won't uncheck 'use default values' + * for attributes which weren't changed + * + * @magentoApiDataFixture Magento/Store/_files/second_website_with_two_stores.php + */ + public function testProductDefaultValuesWithTwoWebsites(): void + { + $productData = [ + ProductInterface::SKU => 'test-1', + ProductInterface::NAME => 'Test 1', + ProductInterface::ATTRIBUTE_SET_ID => 4, + ProductInterface::PRICE => 10, + ProductInterface::STATUS => 1, + ProductInterface::VISIBILITY => 4, + ProductInterface::TYPE_ID => 'simple', + ProductInterface::WEIGHT => 100, + ]; + + $response = $this->saveProduct($productData, 'all'); + + $this->assertEquals($response[ProductInterface::SKU], $productData[ProductInterface::SKU]); + + $this->fixtureProducts[] = $productData[ProductInterface::SKU]; + + $productEditData = [ + ProductInterface::SKU => 'test-1', + ProductInterface::NAME => 'Test 1 changed', + ]; + + $responseAfterEdit = $this->saveProduct($productEditData, 'fixture_third_store'); + + $this->assertEquals($productEditData[ProductInterface::NAME], $responseAfterEdit[ProductInterface::NAME]); + + $store = $this->objectManager->get(Store::class); + /** @var Product $model */ + $model = $this->objectManager->get(Product::class); + $product = $model->load($model->getIdBySku($responseAfterEdit[ProductInterface::SKU])); + + /** @var ScopeOverriddenValue $scopeOverriddenValue */ + $scopeOverriddenValue = $this->objectManager->get(ScopeOverriddenValue::class); + $storeId = $store->load('fixture_third_store', 'code')->getId(); + $this->assertFalse($scopeOverriddenValue->containsValue( + ProductInterface::class, + $product, + 'visibility', + $storeId + )); + + $this->assertFalse($scopeOverriddenValue->containsValue( + ProductInterface::class, + $product, + 'tax_class_id', + $storeId + )); + + $this->assertFalse($scopeOverriddenValue->containsValue( + ProductInterface::class, + $product, + 'status', + $storeId + )); + } +} From 105bc1f22a29ae1be87f611fd43d19cc823aba6e Mon Sep 17 00:00:00 2001 From: Serhiy Yelahin <serhiy.yelahin@transoftgroup.com> Date: Tue, 19 Jan 2021 14:51:23 +0200 Subject: [PATCH 231/242] MC-40384: [Magento Cloud] Order Grid created time showing wrong --- .../Order/Grid/CollectionTest.php | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Grid/CollectionTest.php index d2d71ab880026..abf845aca0d88 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Grid/CollectionTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Grid/CollectionTest.php @@ -7,10 +7,26 @@ namespace Magento\Sales\Model\ResourceModel\Order\Grid; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; -class CollectionTest extends \PHPUnit\Framework\TestCase +class CollectionTest extends TestCase { + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + } + /** * Tests collection properties. * @@ -19,10 +35,8 @@ class CollectionTest extends \PHPUnit\Framework\TestCase */ public function testCollectionCreate(): void { - $objectManager = Bootstrap::getObjectManager(); - /** @var Collection $gridCollection */ - $gridCollection = $objectManager->get(Collection::class); + $gridCollection = $this->objectManager->get(Collection::class); $tableDescription = $gridCollection->getConnection() ->describeTable($gridCollection->getMainTable()); @@ -42,4 +56,25 @@ public function testCollectionCreate(): void self::assertStringContainsString('main_table.', $mappedName); } } + + /** + * Verifies that filter condition date is being converted to config timezone before select sql query + * + * @return void + */ + public function testAddFieldToFilter(): void + { + $filterDate = "2021-01-19 00:00:00"; + /** @var TimezoneInterface $timeZone */ + $timeZone = $this->objectManager->get(TimezoneInterface::class); + /** @var Collection $gridCollection */ + $gridCollection = $this->objectManager->get(Collection::class); + $convertedDate = $timeZone->convertConfigTimeToUtc($filterDate); + + $collection = $gridCollection->addFieldToFilter('created_at', ['qteq' => $filterDate]); + $expectedSelect = "SELECT `main_table`.* FROM `sales_order_grid` AS `main_table` " . + "WHERE (((`main_table`.`created_at` = '{$convertedDate}')))"; + + $this->assertEquals($expectedSelect, $collection->getSelectSql(true)); + } } From 3e3a639fe64ccc2a701c823a23c418976178f214 Mon Sep 17 00:00:00 2001 From: Vasya Tsviklinskyi <tsviklinskyi@gmail.com> Date: Tue, 19 Jan 2021 14:59:16 +0200 Subject: [PATCH 232/242] MC-40376: Auto suggestion box not reappearing after clicking outside the text field --- ...ontAssertDropDownSearchSuggestionActionGroup.xml | 3 +-- ...ntVerifySearchSuggestionByControlButtonsTest.xml | 13 ++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml index 62cb3ac70cbc4..226e30486251c 100644 --- a/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml +++ b/app/code/Magento/Search/Test/Mftf/ActionGroup/StoreFrontAssertDropDownSearchSuggestionActionGroup.xml @@ -19,11 +19,10 @@ <waitForElementVisible selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" stepKey="waitForQuickSearchToBeVisible"/> <fillField selector="{{StorefrontQuickSearchResultsSection.searchTextBox}}" userInput="{{searchQuery}}" stepKey="fillSearchInput"/> <waitForElementVisible selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="WaitForSearchDropDownSuggestion"/> - <see selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="seeDropDownSuggestion"/> <click selector="//div[@class='panel wrapper']" stepKey="clickOnSomewhere"/> <dontSee selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="dontSeeDropDownSuggestion"/> <click selector="{{StorefrontQuickSearchSection.searchPhrase}}" stepKey="clickOnSearchPhrase"/> <pressKey selector="{{StorefrontQuickSearchSection.searchPhrase}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::DOWN]" stepKey="pressDown"/> - <see selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="seeDropDownSuggestionSecond"/> + <waitForElementVisible selector="{{StorefrontQuickSearchSection.searchDropDownSuggestion}}" stepKey="WaitForSearchDropDownSuggestionSecond"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml index e325ecd1fe3ae..b9c491705316c 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/StorefrontVerifySearchSuggestionByControlButtonsTest.xml @@ -19,12 +19,12 @@ </annotations> <before> - <!-- Login as admin --> - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <!-- Create Simple Product --> <createData entity="defaultSimpleProduct" stepKey="simpleProduct"/> + <!-- Login as admin --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <!-- Perform reindex and flush cache --> <actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> <argument name="indices" value=""/> @@ -42,11 +42,10 @@ <!-- Filter the search term --> <actionGroup ref="AdminSearchTermFilterBySearchQueryActionGroup" stepKey="filterByThirdSearchQuery"> - <argument name="searchQuery" value="$$simpleProduct.name$$"/> + <argument name="searchQuery" value="$simpleProduct.name$"/> </actionGroup> <!-- Delete created below search terms --> <actionGroup ref="AdminDeleteSearchTermActionGroup" stepKey="deleteSearchTerms"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> </after> <!-- Go to storefront home page --> @@ -54,12 +53,12 @@ <!-- Storefront quick search by product name --> <actionGroup ref="StorefrontCheckQuickSearchStringActionGroup" stepKey="quickSearchByProductName"> - <argument name="phrase" value="$$simpleProduct.name$$"/> + <argument name="phrase" value="$simpleProduct.name$"/> </actionGroup> <!-- Verify search suggestions and select the suggestion from dropdown options --> <actionGroup ref="StoreFrontAssertDropDownSearchSuggestionActionGroup" stepKey="seeDropDownSearchSuggestion"> - <argument name="searchQuery" value="$$simpleProduct.name$$"/> + <argument name="searchQuery" value="$simpleProduct.name$"/> </actionGroup> </test> </tests> From 07b208151a68ad36d7ba7a417c4e96e28ee8d992 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Tue, 19 Jan 2021 08:03:52 -0600 Subject: [PATCH 233/242] B2B-1640: Add MFTF test for MC-38222 - Adding check on Import History page --- ...NavigateToImportHistoryPageActionGroup.xml | 17 ++++++++++++++ .../Test/Mftf/Page/AdminImportHistoryPage.xml | 12 ++++++++++ ...igurableProductsWithAssignedImagesTest.xml | 8 +++++++ ...dminGridSortColumnAscendingActionGroup.xml | 23 +++++++++++++++++++ ...minGridSortColumnDescendingActionGroup.xml | 23 +++++++++++++++++++ .../Section/AdminDataGridHeaderSection.xml | 5 ++++ 6 files changed, 88 insertions(+) create mode 100644 app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportHistoryPageActionGroup.xml create mode 100644 app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportHistoryPage.xml create mode 100644 app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnAscendingActionGroup.xml create mode 100644 app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnDescendingActionGroup.xml diff --git a/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportHistoryPageActionGroup.xml b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportHistoryPageActionGroup.xml new file mode 100644 index 0000000000000..02a5990b9ad25 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/ActionGroup/AdminNavigateToImportHistoryPageActionGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNavigateToImportHistoryPageActionGroup"> + <annotations> + <description>Navigates to the admin System > Data Transfer > Import History page.</description> + </annotations> + <amOnPage url="{{AdminImportHistoryPage.url}}" stepKey="navigateToImportHistoryPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportHistoryPage.xml b/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportHistoryPage.xml new file mode 100644 index 0000000000000..211d81582793f --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Mftf/Page/AdminImportHistoryPage.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="AdminImportHistoryPage" url="admin/history" area="admin" module="Magento_ImportExport"/> +</pages> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index df7c671d6a5b6..f8768283dfa2d 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -86,6 +86,14 @@ <argument name="indices" value=""/> </actionGroup> + <!-- Admin: Verify Data on Import History Page --> + <actionGroup ref="AdminNavigateToImportHistoryPageActionGroup" stepKey="navigateToImportHistoryPage"/> + <actionGroup ref="AdminGridSortColumnDescendingActionGroup" stepKey="sortColumnByIdDescending"> + <argument name="columnLabel" value="history_id"/> + </actionGroup> + <see userInput="import_configurable_product.csv" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeImportedFile"/> + <see userInput="Created: 4, Updated: 0, Deleted: 0" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeSummary"/> + <!-- Admin: Verify Simple Product 1 on Product Index Page --> <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct1InAdminGrid"> <argument name="product" value="ImportSimple1"/> diff --git a/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnAscendingActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnAscendingActionGroup.xml new file mode 100644 index 0000000000000..c11f0bb1dd720 --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnAscendingActionGroup.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="AdminGridSortColumnAscendingActionGroup"> + <annotations> + <description>Sorts the specified column in ascending order on Admin Grid page.</description> + </annotations> + <arguments> + <argument name="columnLabel" type="string"/> + </arguments> + <conditionalClick selector="{{AdminDataGridHeaderSection.columnByLabel(columnLabel)}}" dependentSelector="{{AdminDataGridHeaderSection.columnNotSorted(columnLabel)}}" visible="true" stepKey="clickColumnIfNotSorted"/> + <waitForPageLoad stepKey="waitForGridLoad1"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.columnByLabel(columnLabel)}}" dependentSelector="{{AdminDataGridHeaderSection.columnSortedDescending(columnLabel)}}" visible="true" stepKey="clickColumnIfDescending"/> + <waitForPageLoad stepKey="waitForGridLoad2"/> + <waitForElementVisible selector="{{AdminDataGridHeaderSection.columnSortedAscending(columnLabel)}}" stepKey="seeColumnAscending"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnDescendingActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnDescendingActionGroup.xml new file mode 100644 index 0000000000000..0d1ab2a8ac8b5 --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridSortColumnDescendingActionGroup.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="AdminGridSortColumnDescendingActionGroup"> + <annotations> + <description>Sorts the specified column in descending order on Admin Grid page.</description> + </annotations> + <arguments> + <argument name="columnLabel" type="string"/> + </arguments> + <conditionalClick selector="{{AdminDataGridHeaderSection.columnByLabel(columnLabel)}}" dependentSelector="{{AdminDataGridHeaderSection.columnNotSorted(columnLabel)}}" visible="true" stepKey="clickColumnIfNotSorted"/> + <waitForPageLoad stepKey="waitForGridLoad1"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.columnByLabel(columnLabel)}}" dependentSelector="{{AdminDataGridHeaderSection.columnSortedAscending(columnLabel)}}" visible="true" stepKey="clickColumnIfAscending"/> + <waitForPageLoad stepKey="waitForGridLoad2"/> + <waitForElementVisible selector="{{AdminDataGridHeaderSection.columnSortedDescending(columnLabel)}}" stepKey="seeColumnDescending"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml index 4ee38e30f98e6..15835aa439b08 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridHeaderSection.xml @@ -27,5 +27,10 @@ <element name="columnCheckbox" type="checkbox" selector="//div[contains(@class,'admin__data-grid-action-columns')]//div[contains(@class, 'admin__field-option')]//label[text() = '{{column}}']/preceding-sibling::input" parameterized="true"/> <element name="perPage" type="select" selector="#product_attributes_listing.product_attributes_listing.listing_top.listing_paging_sizes"/> <element name="attributeName" type="input" selector="//div[text()='{{arg}}']/../preceding-sibling::td//input" parameterized="true"/> + <!--Sorting--> + <element name="columnByLabel" type="text" parameterized="true" selector="th[data-sort='{{columnName}}']"/> + <element name="columnNotSorted" type="text" parameterized="true" selector="th[data-sort='{{columnName}}'].not-sort"/> + <element name="columnSortedAscending" type="text" parameterized="true" selector="th[data-sort='{{columnName}}']._ascend"/> + <element name="columnSortedDescending" type="text" parameterized="true" selector="th[data-sort='{{columnName}}']._descend"/> </section> </sections> From aff2b004973f9587be4abf365fbb33ceff0706c6 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transogtgroup.com> Date: Tue, 19 Jan 2021 16:28:39 +0200 Subject: [PATCH 234/242] MC-40283: Catalog Rule does not work for multi-website with different timezones --- .../Model/Indexer/ReindexRuleProduct.php | 51 +++++++++++++++---- .../Model/Indexer/ReindexRuleProductPrice.php | 38 +++++++++++--- ...ontinueEditCatalogPriceRuleActionGroup.xml | 20 ++++++++ .../Indexer/ReindexRuleProductPriceTest.php | 3 +- .../Model/Indexer/ReindexRuleProductTest.php | 15 ++++-- 5 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndContinueEditCatalogPriceRuleActionGroup.xml diff --git a/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php b/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php index 944710773123f..3e2301f34c4f8 100644 --- a/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php +++ b/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php @@ -6,8 +6,8 @@ namespace Magento\CatalogRule\Model\Indexer; -use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper; use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher; +use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper; use Magento\CatalogRule\Model\Rule; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; @@ -18,6 +18,8 @@ */ class ReindexRuleProduct { + private const ADMIN_WEBSITE_ID = 0; + /** * @var ResourceConnection */ @@ -38,22 +40,30 @@ class ReindexRuleProduct */ private $localeDate; + /** + * @var bool + */ + private $useWebsiteTimezone; + /** * @param ResourceConnection $resource * @param ActiveTableSwitcher $activeTableSwitcher * @param TableSwapper $tableSwapper * @param TimezoneInterface $localeDate + * @param bool $useWebsiteTimezone */ public function __construct( ResourceConnection $resource, ActiveTableSwitcher $activeTableSwitcher, TableSwapper $tableSwapper, - TimezoneInterface $localeDate + TimezoneInterface $localeDate, + bool $useWebsiteTimezone = true ) { $this->resource = $resource; $this->activeTableSwitcher = $activeTableSwitcher; $this->tableSwapper = $tableSwapper; $this->localeDate = $localeDate; + $this->useWebsiteTimezone = $useWebsiteTimezone; } /** @@ -95,18 +105,18 @@ public function execute(Rule $rule, $batchCount, $useAdditionalTable = false) $actionOperator = $rule->getSimpleAction(); $actionAmount = $rule->getDiscountAmount(); $actionStop = $rule->getStopRulesProcessing(); + $fromTimeInAdminTz = $this->parseDateByWebsiteTz((string)$rule->getFromDate(), self::ADMIN_WEBSITE_ID); + $toTimeInAdminTz = $this->parseDateByWebsiteTz((string)$rule->getToDate(), self::ADMIN_WEBSITE_ID); $rows = []; foreach ($websiteIds as $websiteId) { - $scopeTz = new \DateTimeZone( - $this->localeDate->getConfigTimezone(ScopeInterface::SCOPE_WEBSITE, $websiteId) - ); - $fromTime = $rule->getFromDate() - ? (new \DateTime($rule->getFromDate(), $scopeTz))->getTimestamp() - : 0; - $toTime = $rule->getToDate() - ? (new \DateTime($rule->getToDate(), $scopeTz))->getTimestamp() + IndexBuilder::SECONDS_IN_DAY - 1 - : 0; + $fromTime = $this->useWebsiteTimezone + ? $this->parseDateByWebsiteTz((string)$rule->getFromDate(), (int)$websiteId) + : $fromTimeInAdminTz; + $toTime = $this->useWebsiteTimezone + ? $this->parseDateByWebsiteTz((string)$rule->getToDate(), (int)$websiteId) + + ($rule->getToDate() ? IndexBuilder::SECONDS_IN_DAY - 1 : 0) + : $toTimeInAdminTz; foreach ($productIds as $productId => $validationByWebsite) { if (empty($validationByWebsite[$websiteId])) { @@ -140,4 +150,23 @@ public function execute(Rule $rule, $batchCount, $useAdditionalTable = false) return true; } + + /** + * Parse date value by the timezone of the website + * + * @param string $date + * @param int $websiteId + * @return int + */ + private function parseDateByWebsiteTz(string $date, int $websiteId): int + { + if (empty($date)) { + return 0; + } + + $websiteTz = $this->localeDate->getConfigTimezone(ScopeInterface::SCOPE_WEBSITE, $websiteId); + $dateTime = new \DateTime($date, new \DateTimeZone($websiteTz)); + + return $dateTime->getTimestamp(); + } } diff --git a/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProductPrice.php b/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProductPrice.php index 51869f1accbb3..ccc5352567ff0 100644 --- a/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProductPrice.php +++ b/app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProductPrice.php @@ -7,6 +7,7 @@ namespace Magento\CatalogRule\Model\Indexer; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; /** @@ -39,25 +40,33 @@ class ReindexRuleProductPrice */ private $pricesPersistor; + /** + * @var bool + */ + private $useWebsiteTimezone; + /** * @param StoreManagerInterface $storeManager * @param RuleProductsSelectBuilder $ruleProductsSelectBuilder * @param ProductPriceCalculator $productPriceCalculator * @param TimezoneInterface $localeDate * @param RuleProductPricesPersistor $pricesPersistor + * @param bool $useWebsiteTimezone */ public function __construct( StoreManagerInterface $storeManager, RuleProductsSelectBuilder $ruleProductsSelectBuilder, ProductPriceCalculator $productPriceCalculator, TimezoneInterface $localeDate, - RuleProductPricesPersistor $pricesPersistor + RuleProductPricesPersistor $pricesPersistor, + bool $useWebsiteTimezone = true ) { $this->storeManager = $storeManager; $this->ruleProductsSelectBuilder = $ruleProductsSelectBuilder; $this->productPriceCalculator = $productPriceCalculator; $this->localeDate = $localeDate; $this->pricesPersistor = $pricesPersistor; + $this->useWebsiteTimezone = $useWebsiteTimezone; } /** @@ -82,11 +91,9 @@ public function execute(int $batchCount, ?int $productId = null, bool $useAdditi $prevKey = null; $storeGroup = $this->storeManager->getGroup($website->getDefaultGroupId()); - $currentDate = $this->localeDate->scopeDate($storeGroup->getDefaultStoreId(), null, true); - $previousDate = (clone $currentDate)->modify('-1 day'); - $previousDate->setTime(23, 59, 59); - $nextDate = (clone $currentDate)->modify('+1 day'); - $nextDate->setTime(0, 0, 0); + $dateInterval = $this->useWebsiteTimezone + ? $this->getDateInterval((int)$storeGroup->getDefaultStoreId()) + : $this->getDateInterval(Store::DEFAULT_STORE_ID); while ($ruleData = $productsStmt->fetch()) { $ruleProductId = $ruleData['product_id']; @@ -107,7 +114,7 @@ public function execute(int $batchCount, ?int $productId = null, bool $useAdditi /** * Build prices for each day */ - foreach ([$previousDate, $currentDate, $nextDate] as $date) { + foreach ($dateInterval as $date) { $time = $date->getTimestamp(); if (($ruleData['from_time'] == 0 || $time >= $ruleData['from_time']) && ($ruleData['to_time'] == 0 || @@ -157,4 +164,21 @@ public function execute(int $batchCount, ?int $productId = null, bool $useAdditi return true; } + + /** + * Retrieve date sequence in store time zone + * + * @param int $storeId + * @return \DateTime[] + */ + private function getDateInterval(int $storeId): array + { + $currentDate = $this->localeDate->scopeDate($storeId, null, true); + $previousDate = (clone $currentDate)->modify('-1 day'); + $previousDate->setTime(23, 59, 59); + $nextDate = (clone $currentDate)->modify('+1 day'); + $nextDate->setTime(0, 0, 0); + + return [$previousDate, $currentDate, $nextDate]; + } } diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndContinueEditCatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndContinueEditCatalogPriceRuleActionGroup.xml new file mode 100644 index 0000000000000..cf8499ca1b466 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/SaveAndContinueEditCatalogPriceRuleActionGroup.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="SaveAndContinueEditCatalogPriceRuleActionGroup"> + <annotations> + <description>Clicks on Save and Continue Edit. Validates that the Success Message is present and correct on the Admin Catalog Price Rule creation/edit page.</description> + </annotations> + + <waitForElementVisible selector="{{AdminNewCatalogPriceRule.saveAndContinue}}" stepKey="waitForSaveAndContinueEditButton"/> + <click selector="{{AdminNewCatalogPriceRule.saveAndContinue}}" stepKey="saveAndContinueEdit"/> + <see selector="{{AdminCategoryMessagesSection.SuccessMessage}}" userInput="You saved the rule." stepKey="assertSuccess"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductPriceTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductPriceTest.php index 7f22634f9343d..230a6e3860950 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductPriceTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductPriceTest.php @@ -64,7 +64,8 @@ protected function setUp(): void $this->ruleProductsSelectBuilderMock, $this->productPriceCalculatorMock, $this->localeDate, - $this->pricesPersistorMock + $this->pricesPersistorMock, + true ); } diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductTest.php index ddb6a85ed614a..50f4eb0805ed2 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/Indexer/ReindexRuleProductTest.php @@ -21,6 +21,8 @@ class ReindexRuleProductTest extends TestCase { + private const ADMIN_WEBSITE_ID = 0; + /** * @var ReindexRuleProduct */ @@ -57,7 +59,8 @@ protected function setUp(): void $this->resourceMock, $this->activeTableSwitcherMock, $this->tableSwapperMock, - $this->localeDateMock + $this->localeDateMock, + true ); } @@ -85,6 +88,7 @@ public function testExecuteIfRuleWithoutWebsiteIds() public function testExecute() { $websiteId = 3; + $adminTimeZone = 'America/Chicago'; $websiteTz = 'America/Los_Angeles'; $productIds = [ 4 => [$websiteId => 1], @@ -123,10 +127,11 @@ public function testExecute() $ruleMock->expects($this->once())->method('getDiscountAmount')->willReturn(43); $ruleMock->expects($this->once())->method('getStopRulesProcessing')->willReturn(true); - $this->localeDateMock->expects($this->once()) - ->method('getConfigTimezone') - ->with(ScopeInterface::SCOPE_WEBSITE, $websiteId) - ->willReturn($websiteTz); + $this->localeDateMock->method('getConfigTimezone') + ->willReturnMap([ + [ScopeInterface::SCOPE_WEBSITE, self::ADMIN_WEBSITE_ID, $adminTimeZone], + [ScopeInterface::SCOPE_WEBSITE, $websiteId, $websiteTz], + ]); $batchRows = [ [ From 3f75f677009571f84bfa619eb6e545c8d62befad Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Tue, 19 Jan 2021 17:42:54 -0600 Subject: [PATCH 235/242] B2B-1640: Add MFTF test for MC-38222 - Moving MFTF data to data files --- .../ImportExport/Test/Mftf/Data/ImportData.xml | 8 ++++++++ ...AndConfigurableProductsWithAssignedImagesTest.xml | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml b/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml index 6160a12223552..5a883af443348 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Data/ImportData.xml @@ -8,6 +8,12 @@ <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <!-- Common Messages --> + <entity name="ImportCommonMessages"> + <data key="validFile">File is valid! To start import process press "Import" button</data> + <data key="success">Import successfully done</data> + </entity> + <!-- Categories --> <entity name="Import1" type="category"> <data key="name">Import1</data> @@ -60,6 +66,8 @@ <requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity> </entity> <entity name="ImportConfigurable" type="product"> + <data key="fileName">import_configurable_product.csv</data> + <data key="importSummary">Created: 4, Updated: 0, Deleted: 0</data> <data key="name">import-configurable</data> <data key="sku">import-configurable</data> <data key="type_id">configurable</data> diff --git a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml index f8768283dfa2d..a046724f9ac8d 100644 --- a/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml +++ b/app/code/Magento/ImportExport/Test/Mftf/Test/AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest.xml @@ -71,14 +71,14 @@ <!-- Import Configurable Product with Simple Child Products & Assert No Errors --> <actionGroup ref="AdminNavigateToImportPageActionGroup" stepKey="navigateToImportPage"/> <actionGroup ref="AdminFillImportFormActionGroup" stepKey="fillImportForm"> - <argument name="importFile" value="import_configurable_product.csv"/> + <argument name="importFile" value="{{ImportConfigurable.fileName}}"/> </actionGroup> <actionGroup ref="AdminClickCheckDataImportActionGroup" stepKey="clickCheckData"/> - <see selector="{{AdminImportValidationMessagesSection.success}}" userInput="File is valid! To start import process press "Import" button" stepKey="seeCheckDataResultMessage"/> + <see selector="{{AdminImportValidationMessagesSection.success}}" userInput="{{ImportCommonMessages.validFile}}" stepKey="seeCheckDataResultMessage"/> <dontSeeElementInDOM selector="{{AdminImportValidationMessagesSection.importErrorList}}" stepKey="dontSeeErrorMessage"/> <actionGroup ref="AdminClickImportActionGroup" stepKey="clickImport"/> - <see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="Created: 4, Updated: 0, Deleted: 0" stepKey="seeNoticeMessage"/> - <see selector="{{AdminImportValidationMessagesSection.messageByType('success')}}" userInput="Import successfully done" stepKey="seeImportMessage"/> + <see selector="{{AdminImportValidationMessagesSection.notice}}" userInput="{{ImportConfigurable.importSummary}}" stepKey="seeNoticeMessage"/> + <see selector="{{AdminImportValidationMessagesSection.messageByType('success')}}" userInput="{{ImportCommonMessages.success}}" stepKey="seeImportMessage"/> <dontSeeElementInDOM selector="{{AdminImportValidationMessagesSection.importErrorList}}" stepKey="dontSeeErrorMessage2"/> <!-- Reindex --> @@ -91,8 +91,8 @@ <actionGroup ref="AdminGridSortColumnDescendingActionGroup" stepKey="sortColumnByIdDescending"> <argument name="columnLabel" value="history_id"/> </actionGroup> - <see userInput="import_configurable_product.csv" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeImportedFile"/> - <see userInput="Created: 4, Updated: 0, Deleted: 0" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeSummary"/> + <see userInput="{{ImportConfigurable.fileName}}" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeImportedFile"/> + <see userInput="{{ImportConfigurable.importSummary}}" selector="{{AdminDataGridTableSection.firstRow}}" stepKey="seeSummary"/> <!-- Admin: Verify Simple Product 1 on Product Index Page --> <actionGroup ref="AssertProductOnAdminGridActionGroup" stepKey="assertSimpleProduct1InAdminGrid"> From 89123706aa430ee2c98fe641f23199351a419638 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 20 Jan 2021 11:15:45 +0200 Subject: [PATCH 236/242] MC-39550: Create automated test for: "Add new website to products using mass product update and run cron." --- .../Model/Attribute/Backend/ConsumerWebsiteAssignTest.php | 2 +- .../Catalog/_files/detach_product_website_quene_data.php | 4 ++-- .../Catalog/_files/update_product_website_quene_data.php | 2 +- .../_files/update_product_website_quene_data_rollback.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php index e895a886e44e7..0edddd1b34f6f 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Attribute/Backend/ConsumerWebsiteAssignTest.php @@ -90,7 +90,7 @@ protected function setUp(): void } /** - * @return void + * @inheritdoc */ protected function tearDown(): void { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php index ab03ff5bf6b65..e862e95cbd3e4 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/detach_product_website_quene_data.php @@ -35,7 +35,7 @@ $websiteId = (int)$websiteRepository->get('second_website')->getId(); $bulkDescription = __('Update attributes for ' . 1 . ' selected products'); $dataToEncode = [ - 'meta_information' => 'Update website assign', + 'meta_information' => 'Detach website', 'product_ids' => $productIds, 'store_id' => 0, 'website_id' => $websiteId, @@ -51,7 +51,7 @@ 'topic_name' => 'product_action_attribute.website.update', 'serialized_data' => $jsonEncoder->serialize($dataToEncode), 'status' => OperationInterface::STATUS_TYPE_OPEN, - ] + ], ]; $bulkManagement->scheduleBulk( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php index dca8fb26c0b55..6feffc2a5fb3a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data.php @@ -52,7 +52,7 @@ 'topic_name' => 'product_action_attribute.website.update', 'serialized_data' => $jsonEncoder->serialize($dataToEncode), 'status' => OperationInterface::STATUS_TYPE_OPEN, - ] + ], ]; $bulkManagement->scheduleBulk( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php index 5273947cd28ea..85336635f2e08 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/update_product_website_quene_data_rollback.php @@ -15,4 +15,4 @@ $deleteTopicRelatedMessages->execute('product_action_attribute.website.update'); Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/second_product_simple_rollback.php'); -Resolver::getInstance()->requireDataFixture('Magento/Store/_files/second_website_with_store_group_and_store_rollback.php'); +Resolver::getInstance()->requireDataFixture('Magento/Store/_files/second_website_with_two_stores_rollback.php'); From f2231f8d953bb650c3462a824716fd8972c6bb6c Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 20 Jan 2021 11:27:26 +0200 Subject: [PATCH 237/242] MC-40463: Vimeo simple API stop working as expected --- ...oductVideoStorefrontProductPageActionGroup.xml | 1 + .../Magento/ProductVideo/etc/csp_whitelist.xml | 6 ++++++ .../adminhtml/web/js/get-video-information.js | 15 ++++++++------- lib/web/fotorama/fotorama.js | 9 ++++++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoStorefrontProductPageActionGroup.xml b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoStorefrontProductPageActionGroup.xml index 61747c331247f..53432ec0fd6ac 100644 --- a/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoStorefrontProductPageActionGroup.xml +++ b/app/code/Magento/ProductVideo/Test/Mftf/ActionGroup/AssertProductVideoStorefrontProductPageActionGroup.xml @@ -17,6 +17,7 @@ <argument name="videoType" type="string" defaultValue="youtube"/> </arguments> + <waitForElementVisible selector="{{StorefrontProductInfoMainSection.productVideo(videoType)}}" stepKey="waitVideoElementVisible"/> <seeElement selector="{{StorefrontProductInfoMainSection.productVideo(videoType)}}" stepKey="seeProductVideoDataType"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/ProductVideo/etc/csp_whitelist.xml b/app/code/Magento/ProductVideo/etc/csp_whitelist.xml index ca4536057104d..2e091440330b7 100644 --- a/app/code/Magento/ProductVideo/etc/csp_whitelist.xml +++ b/app/code/Magento/ProductVideo/etc/csp_whitelist.xml @@ -14,6 +14,7 @@ <value id="google_video" type="host">www.googleapis.com</value> <value id="vimeo" type="host">vimeo.com</value> <value id="www_vimeo" type="host">www.vimeo.com</value> + <value id="vimeo_cdn" type="host">*.vimeocdn.com</value> </values> </policy> <policy id="img-src"> @@ -21,5 +22,10 @@ <value id="vimeo_cdn" type="host">*.vimeocdn.com</value> </values> </policy> + <policy id="frame-src"> + <values> + <value id="player_vimeo" type="host">player.vimeo.com</value> + </values> + </policy> </policies> </csp_whitelist> diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js index cb56a085304a7..4b3c1b7f8eec3 100644 --- a/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js +++ b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js @@ -497,20 +497,20 @@ define([ var tmp, respData; - if (data.length < 1) { + if (!data) { this._onRequestError($.mage.__('Video not found')); return null; } - tmp = data[0]; + tmp = data; respData = { duration: this._formatVimeoDuration(tmp.duration), - channel: tmp['user_name'], - channelId: tmp['user_url'], + channel: tmp['author_name'], + channelId: tmp['author_url'], uploaded: tmp['upload_date'], title: tmp.title, description: tmp.description.replace(/( |<([^>]+)>)/ig, ''), - thumbnail: tmp['thumbnail_large'], + thumbnail: tmp['thumbnail_url'], videoId: videoInfo.id, videoProvider: videoInfo.type }; @@ -539,10 +539,11 @@ define([ ); } else if (type === 'vimeo') { $.ajax({ - url: 'https://www.vimeo.com/api/v2/video/' + id + '.json', + url: 'https://vimeo.com/api/oembed.json', dataType: 'jsonp', data: { - format: 'json' + format: 'json', + url: 'https://vimeo.com/' + id }, timeout: 5000, success: $.proxy(_onVimeoLoaded, self), diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 314949bd2f4cf..f268c9aa73667 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -858,13 +858,16 @@ fotoramaVersion = '4.6.4'; dataFrame.thumbsReady = true; } else if (video.type === 'vimeo') { $.ajax({ - url: getProtocol() + 'vimeo.com/api/v2/video/' + video.id + '.json', + url: getProtocol() + 'vimeo.com/api/oembed.json', + data: { + url: 'https://vimeo.com/' + video.id + }, dataType: 'jsonp', success: function (json) { dataFrame.thumbsReady = true; updateData(data, { - img: json[0].thumbnail_large, - thumb: json[0].thumbnail_small + img: json[0].thumbnail_url, + thumb: json[0].thumbnail_url }, dataFrame.i, fotorama); } }); From 8059762db4f3db35449a1c681e61f1c9c777238d Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 20 Jan 2021 13:20:18 +0200 Subject: [PATCH 238/242] MC-39722: Create automated test for: "Dropdown attribute in flat product" --- .../Indexer/Product/Flat/Action/FullTest.php | 144 +++++++++++++----- 1 file changed, 107 insertions(+), 37 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php index 4313f95f24a8e..1fa6c1a8889b8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php @@ -3,40 +3,49 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Model\Indexer\Product\Flat\Action; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Block\Product\ListProduct; use Magento\Catalog\Model\CategoryFactory; use Magento\Catalog\Model\Indexer\Product\Flat\Processor; use Magento\Catalog\Model\Indexer\Product\Flat\State; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory; +use Magento\Catalog\Model\ResourceModel\Product\Flat as FlatResource; use Magento\CatalogSearch\Model\Indexer\Fulltext; +use Magento\Eav\Api\AttributeOptionManagementInterface; use Magento\Framework\Indexer\IndexerRegistry; +use Magento\Framework\ObjectManagerInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; -use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Indexer\TestCase; /** * Full reindex Test */ -class FullTest extends \Magento\TestFramework\Indexer\TestCase +class FullTest extends TestCase { - /** - * @var State - */ - protected $_state; + /** @var State */ + protected $state; - /** - * @var Processor - */ - protected $_processor; + /** @var Processor */ + protected $processor; - /** - * @var ObjectManager - */ + /** @var ObjectManagerInterface */ private $objectManager; + /** @var FlatResource */ + private $flatResource; + + /** @var AttributeOptionManagementInterface */ + private $optionManagement; + + /** @var ProductRepositoryInterface */ + private $productRepository; + /** * @inheritdoc */ @@ -58,9 +67,14 @@ public static function setUpBeforeClass(): void */ protected function setUp(): void { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); - $this->_state = $this->objectManager->get(State::class); - $this->_processor = $this->objectManager->get(Processor::class); + $this->state = $this->objectManager->get(State::class); + $this->processor = $this->objectManager->get(Processor::class); + $this->flatResource = $this->objectManager->get(FlatResource::class); + $this->optionManagement = $this->objectManager->get(AttributeOptionManagementInterface::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); } /** @@ -68,11 +82,13 @@ protected function setUp(): void * @magentoAppIsolation enabled * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * + * @return void */ - public function testReindexAll() + public function testReindexAll(): void { - $this->assertTrue($this->_state->isFlatEnabled()); - $this->_processor->reindexAll(); + $this->assertTrue($this->state->isFlatEnabled()); + $this->processor->reindexAll(); $categoryFactory = $this->objectManager->get(CategoryFactory::class); $listProduct = $this->objectManager->get(ListProduct::class); @@ -98,11 +114,13 @@ public function testReindexAll() * @magentoDataFixture Magento/Catalog/_files/product_simple_multistore.php * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 * @magentoConfigFixture fixturestore_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testReindexAllMultipleStores() + public function testReindexAllMultipleStores(): void { - $this->assertTrue($this->_state->isFlatEnabled()); - $this->_processor->reindexAll(); + $this->assertTrue($this->state->isFlatEnabled()); + $this->processor->reindexAll(); /** @var ProductCollectionFactory $productCollectionFactory */ $productCollectionFactory = $this->objectManager->create(ProductCollectionFactory::class); @@ -116,24 +134,76 @@ public function testReindexAllMultipleStores() $store->getId() => 'StoreTitle', ]; - foreach ($expectedData as $storeId => $productName) { - $storeManager->setCurrentStore($storeId); - $productCollection = $productCollectionFactory->create(); - - $this->assertTrue( - $productCollection->isEnabledFlat(), - 'Flat should be enabled for product collection.' - ); + try { + foreach ($expectedData as $storeId => $productName) { + $storeManager->setCurrentStore($storeId); + $productCollection = $productCollectionFactory->create(); + + $this->assertTrue( + $productCollection->isEnabledFlat(), + 'Flat should be enabled for product collection.' + ); + + $productCollection->addIdFilter(1)->addAttributeToSelect(ProductInterface::NAME); + + $this->assertEquals( + $productName, + $productCollection->getFirstItem()->getName(), + 'Wrong product name specified per store.' + ); + } + } finally { + $storeManager->setCurrentStore($currentStore); + } + } - $productCollection->addIdFilter(1)->addAttributeToSelect(ProductInterface::NAME); + /** + * @magentoDbIsolation disabled + * + * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * @magentoDataFixture Magento/Catalog/_files/dropdown_attribute.php + * @magentoDataFixture Magento/Catalog/_files/second_product_simple.php + * + * @return void + */ + public function testCheckDropdownAttributeInFlat(): void + { + $attributeCode = 'dropdown_attribute'; + $options = $this->optionManagement->getItems($this->flatResource->getTypeId(), $attributeCode); + $attributeValue = $options[1]->getValue(); + $this->updateProduct('simple2', $attributeCode, $attributeValue); + $this->processor->reindexAll(); + $this->assertFlatColumnValue($attributeCode, $attributeValue); + } - $this->assertEquals( - $productName, - $productCollection->getFirstItem()->getName(), - 'Wrong product name specified per store.' - ); - } + /** + * Assert if column exist and column value in flat table + * + * @param string $attributeCode + * @param string $value + * @return void + */ + private function assertFlatColumnValue(string $attributeCode, string $value): void + { + $connect = $this->flatResource->getConnection(); + $tableName = $this->flatResource->getFlatTableName(); + $this->assertTrue($connect->tableColumnExists($tableName, $attributeCode)); + $select = $connect->select()->from($tableName, $attributeCode); + $this->assertEquals($value, $connect->fetchOne($select)); + } - $storeManager->setCurrentStore($currentStore); + /** + * Update product + * + * @param string $sku + * @param string $attributeCode + * @param string $value + * @return void + */ + private function updateProduct(string $sku, string $attributeCode, string $value): void + { + $product = $this->productRepository->get($sku); + $product->setData($attributeCode, $value); + $this->productRepository->save($product); } } From 9f5e7060164a7ae3099a850682433c7bb6de3426 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 20 Jan 2021 15:27:09 +0200 Subject: [PATCH 239/242] MC-40081: Create automated test for: "Disable flat product" --- .../Indexer/Product/Flat/ProcessorTest.php | 120 ++++++++++++++---- 1 file changed, 96 insertions(+), 24 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/ProcessorTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/ProcessorTest.php index 5c376517ed143..5b9266dc11371 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/ProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/ProcessorTest.php @@ -3,33 +3,58 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Model\Indexer\Product\Flat; use Magento\Catalog\Model\Product\Attribute\Repository; +use Magento\Framework\Indexer\StateInterface; +use Magento\Framework\Indexer\StateInterfaceFactory; +use Magento\Indexer\Model\ResourceModel\Indexer\State as StateResource; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Indexer\TestCase; +use Magento\TestFramework\ObjectManager; /** * Integration tests for \Magento\Catalog\Model\Indexer\Product\Flat\Processor. */ -class ProcessorTest extends \Magento\TestFramework\Indexer\TestCase +class ProcessorTest extends TestCase { /** - * @var \Magento\Catalog\Model\Indexer\Product\Flat\State + * @var ObjectManager */ - protected $_state; + private $objectManager; /** - * @var \Magento\Catalog\Model\Indexer\Product\Flat\Processor + * @var State */ - protected $_processor; + private $state; + /** + * @var Processor + */ + private $processor; + + /** + * @var StateResource + */ + private $stateResource; + + /** + * @var StateInterfaceFactory; + */ + private $stateFactory; + + /** + * @inheritdoc + */ protected function setUp(): void { - $this->_state = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Catalog\Model\Indexer\Product\Flat\State::class - ); - $this->_processor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Catalog\Model\Indexer\Product\Flat\Processor::class - ); + $this->objectManager = Bootstrap::getObjectManager(); + $this->state = $this->objectManager->get(State::class); + $this->processor = $this->objectManager->get(Processor::class); + $this->stateResource = $this->objectManager->get(StateResource::class); + $this->stateFactory = $this->objectManager->get(StateInterfaceFactory::class); } /** @@ -37,11 +62,13 @@ protected function setUp(): void * @magentoAppIsolation enabled * @magentoAppArea adminhtml * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testEnableProductFlat() + public function testEnableProductFlat(): void { - $this->assertTrue($this->_state->isFlatEnabled()); - $this->assertTrue($this->_processor->getIndexer()->isInvalid()); + $this->assertTrue($this->state->isFlatEnabled()); + $this->assertTrue($this->processor->getIndexer()->isInvalid()); } /** @@ -50,8 +77,10 @@ public function testEnableProductFlat() * @magentoAppArea adminhtml * @magentoDataFixture Magento/Catalog/_files/multiple_products.php * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testSaveAttribute() + public function testSaveAttribute(): void { /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -61,8 +90,7 @@ public function testSaveAttribute() /** @var \Magento\Catalog\Model\ResourceModel\Product $productResource */ $productResource = $product->getResource(); $productResource->getAttribute('sku')->setData('used_for_sort_by', 1)->save(); - - $this->assertTrue($this->_processor->getIndexer()->isInvalid()); + $this->assertTrue($this->processor->getIndexer()->isInvalid()); } /** @@ -71,8 +99,10 @@ public function testSaveAttribute() * @magentoAppArea adminhtml * @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_attribute_in_flat.php * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testDeleteAttribute() + public function testDeleteAttribute(): void { /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $model */ $model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() @@ -83,8 +113,7 @@ public function testDeleteAttribute() $productAttrubute = $productAttributeRepository->get('flat_attribute'); $productAttributeId = $productAttrubute->getAttributeId(); $model->load($productAttributeId)->delete(); - - $this->assertTrue($this->_processor->getIndexer()->isInvalid()); + $this->assertTrue($this->processor->getIndexer()->isInvalid()); } /** @@ -93,10 +122,12 @@ public function testDeleteAttribute() * @magentoAppArea adminhtml * @magentoDataFixture Magento/Store/_files/core_fixturestore.php * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testAddNewStore() + public function testAddNewStore(): void { - $this->assertTrue($this->_processor->getIndexer()->isInvalid()); + $this->assertTrue($this->processor->getIndexer()->isInvalid()); } /** @@ -104,8 +135,10 @@ public function testAddNewStore() * @magentoAppIsolation enabled * @magentoAppArea adminhtml * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 + * + * @return void */ - public function testAddNewStoreGroup() + public function testAddNewStoreGroup(): void { /** @var \Magento\Store\Model\Group $storeGroup */ $storeGroup = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -115,6 +148,45 @@ public function testAddNewStoreGroup() ['website_id' => 1, 'name' => 'New Store Group', 'root_category_id' => 2, 'group_id' => null] ); $storeGroup->save(); - $this->assertTrue($this->_processor->getIndexer()->isInvalid()); + $this->assertTrue($this->processor->getIndexer()->isInvalid()); + } + + /** + * @magentoDbIsolation disabled + * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 0 + * + * @return void + */ + public function testReindexAllWithProductFlatDisabled(): void + { + $this->updateIndexerStatus(); + $this->processor->reindexAll(); + $state = $this->getIndexerState(); + $this->assertEquals(StateInterface::STATUS_INVALID, $state->getStatus()); + } + + /** + * Update status for indexer + * + * @param string $status + * @return void + */ + private function updateIndexerStatus(string $status = StateInterface::STATUS_INVALID): void + { + $state = $this->getIndexerState(); + $state->setStatus($status); + $this->stateResource->save($state); + } + + /** + * Get Indexer state + * + * @return StateInterface + */ + private function getIndexerState(): StateInterface + { + $state = $this->stateFactory->create(); + + return $state->loadByIndexer(State::INDEXER_ID); } } From bc14738eadea851875ac30eca2a2f1c6f6cfacd0 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 20 Jan 2021 18:10:13 +0200 Subject: [PATCH 240/242] MC-39722: Create automated test for: "Dropdown attribute in flat product" --- .../Model/Indexer/Product/Flat/Action/FullTest.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php index 1fa6c1a8889b8..bc96b30d55c04 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Indexer/Product/Flat/Action/FullTest.php @@ -29,10 +29,10 @@ class FullTest extends TestCase { /** @var State */ - protected $state; + private $state; /** @var Processor */ - protected $processor; + private $processor; /** @var ObjectManagerInterface */ private $objectManager; @@ -46,6 +46,9 @@ class FullTest extends TestCase /** @var ProductRepositoryInterface */ private $productRepository; + /** @var Full */ + private $action; + /** * @inheritdoc */ @@ -75,6 +78,7 @@ protected function setUp(): void $this->flatResource = $this->objectManager->get(FlatResource::class); $this->optionManagement = $this->objectManager->get(AttributeOptionManagementInterface::class); $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->action = $this->objectManager->get(Full::class); } /** @@ -172,7 +176,7 @@ public function testCheckDropdownAttributeInFlat(): void $options = $this->optionManagement->getItems($this->flatResource->getTypeId(), $attributeCode); $attributeValue = $options[1]->getValue(); $this->updateProduct('simple2', $attributeCode, $attributeValue); - $this->processor->reindexAll(); + $this->action->execute(); $this->assertFlatColumnValue($attributeCode, $attributeValue); } From 152b41b3f8bd6bc410e0b20ede03cfaeb1143d87 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 21 Jan 2021 13:12:00 +0200 Subject: [PATCH 241/242] MC-23915: Revert 23915 because it caused static tests failure --- .../Order/Creditmemo/Grid/Collection.php | 28 ----------- .../Creditmemo/Order/Grid/Collection.php | 28 ----------- .../sales_order_creditmemo_grid.xml | 4 +- .../sales_order_view_creditmemo_grid.xml | 4 +- .../Order/Creditmemo/Grid/CollectionTest.php | 46 ------------------- .../Creditmemo/Order/Grid/CollectionTest.php | 46 ------------------- 6 files changed, 4 insertions(+), 152 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php delete mode 100644 dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php index 46e26c97556e6..6960b34b1b32f 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php @@ -33,32 +33,4 @@ public function __construct( ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); } - - /** - * @inheritDoc - */ - protected function _translateCondition($field, $condition) - { - if ($field !== 'order_currency_code' - && !isset($this->_map['fields'][$field]) - ) { - $this->_map['fields'][$field] = 'main_table.' . $field; - } - - return parent::_translateCondition($field, $condition); - } - - /** - * @inheritDoc - */ - protected function _renderFiltersBefore() - { - $this->getSelect()->joinLeft( - ['cgf' => $this->getTable('sales_order_grid')], - 'main_table.order_id = cgf.entity_id', - [ - 'order_currency_code' => 'order_currency_code', - ] - ); - } } diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php index 4d446b6c7620d..eab3998eebcbd 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php @@ -33,32 +33,4 @@ public function __construct( ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); } - - /** - * @inheritDoc - */ - protected function _translateCondition($field, $condition) - { - if ($field !== 'order_currency_code' - && !isset($this->_map['fields'][$field]) - ) { - $this->_map['fields'][$field] = 'main_table.' . $field; - } - - return parent::_translateCondition($field, $condition); - } - - /** - * @inheritDoc - */ - protected function _renderFiltersBefore() - { - $this->getSelect()->joinLeft( - ['cgf' => $this->getTable('sales_order_grid')], - 'main_table.order_id = cgf.entity_id', - [ - 'order_currency_code' => 'order_currency_code', - ] - ); - } } diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml index a7e79f23b1cca..1fc8d41ce0900 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_creditmemo_grid.xml @@ -194,14 +194,14 @@ <visible>false</visible> </settings> </column> - <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> + <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\Price"> <settings> <filter>textRange</filter> <label translate="true">Subtotal</label> <visible>false</visible> </settings> </column> - <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> + <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\Price"> <settings> <filter>textRange</filter> <label translate="true">Shipping & Handling</label> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml index 16a7e00b24bb3..09be15c5a3cf9 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_view_creditmemo_grid.xml @@ -207,14 +207,14 @@ <visible>false</visible> </settings> </column> - <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> + <column name="subtotal" class="Magento\Sales\Ui\Component\Listing\Column\Price"> <settings> <filter>textRange</filter> <label translate="true">Subtotal</label> <visible>false</visible> </settings> </column> - <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> + <column name="shipping_and_handling" class="Magento\Sales\Ui\Component\Listing\Column\Price"> <settings> <filter>textRange</filter> <label translate="true">Shipping & Handling</label> diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php deleted file mode 100644 index 4a96a381309db..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/CollectionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid; - -use Magento\Framework\ObjectManagerInterface; -use Magento\TestFramework\Helper\Bootstrap; -use PHPUnit\Framework\TestCase; - -/** - * Test Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid - */ -class CollectionTest extends TestCase -{ - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @inheritDoc - */ - protected function setUp(): void - { - $this->objectManager = Bootstrap::getObjectManager(); - } - - /** - * @magentoDataFixture Magento/Sales/_files/creditmemo_list.php - * - * @return void - */ - public function testCollectionOrderCurrencyCodeExist(): void - { - /** @var $collection Collection */ - $collection = $this->objectManager->get(Collection::class); - $collection->addFieldToFilter('increment_id', ['eq' => '456']); - foreach ($collection as $item) { - $this->assertNotNull($item->getOrderCurrencyCode()); - } - } -} diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php deleted file mode 100644 index 0b7908a122293..0000000000000 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/CollectionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid; - -use Magento\Framework\ObjectManagerInterface; -use Magento\TestFramework\Helper\Bootstrap; -use PHPUnit\Framework\TestCase; - -/** - * Test Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid\Order\Grid - */ -class CollectionTest extends TestCase -{ - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @inheritDoc - */ - protected function setUp(): void - { - $this->objectManager = Bootstrap::getObjectManager(); - } - - /** - * @magentoDataFixture Magento/Sales/_files/creditmemo_list.php - * - * @return void - */ - public function testCollectionOrderCurrencyCodeExist(): void - { - /** @var $collection Collection */ - $collection = $this->objectManager->get(Collection::class); - $collection->addFieldToFilter('increment_id', ['eq' => '456']); - foreach ($collection as $item) { - $this->assertNotNull($item->getOrderCurrencyCode()); - } - } -} From 7b9f198f703b3707ebf03d03cdc9ac1f66abe118 Mon Sep 17 00:00:00 2001 From: David Haecker <dhaecker@magento.com> Date: Thu, 21 Jan 2021 10:37:03 -0600 Subject: [PATCH 242/242] B2B-1640: Add MFTF test for MC-38222 - Removing gift card references from import csv --- .../tests/_data/import_configurable_product.csv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/acceptance/tests/_data/import_configurable_product.csv b/dev/tests/acceptance/tests/_data/import_configurable_product.csv index 6eaf2a2429a74..880e0bfb64c2e 100644 --- a/dev/tests/acceptance/tests/_data/import_configurable_product.csv +++ b/dev/tests/acceptance/tests/_data/import_configurable_product.csv @@ -1,5 +1,5 @@ -sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,giftcard_type,giftcard_allow_open_amount,giftcard_open_amount_min,giftcard_open_amount_max,giftcard_amount,use_config_is_redeemable,giftcard_is_redeemable,use_config_lifetime,giftcard_lifetime,use_config_allow_message,giftcard_allow_message,use_config_email_template,giftcard_email_template,associated_skus,downloadable_links,downloadable_samples,configurable_variations,configurable_variation_labels -import-simple1,,Default,simple,Default Category/Import1,base,import-simple1,,,12,1,Taxable Goods,Not Visible Individually,12,,,,import-simple1,Conf11,Conf11,Conf11 ,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option1,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/m/a/magento-logo.png,Magento Logo,,,,,,,,,,,,,,,,,,,,,,,,,, -import-simple2,,Default,simple,Default Category/Import1,base,import-simple2,,,12,1,Taxable Goods,Not Visible Individually,15,,,,import-simple2,Conf11,Conf11,Conf11 ,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option2,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/t/e/test_image.jpg,Test Image,,,,,,,,,,,,,,,,,,,,,,,,,, -import-simple3,,Default,simple,Default Category/Import1,base,import-simple3,,,12,1,Taxable Goods,Not Visible Individually,10,,,,import-simple3,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option3,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -import-configurable,,Default,configurable,Default Category/Import1,base,import-configurable,,,12,1,Taxable Goods,"Catalog, Search",,,,,import-configurable,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,Use config,,,,,,,Use config,,gift_wrapping_available=Use config,0,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,",,",,,,,,,,,,,,,,,,,,,,,,,,,"sku=import-simple1,import_attribute1=option1|sku=import-simple2,import_attribute1=option2|sku=import-simple3,import_attribute1=option3",import_attribute1=import_attribute1 \ No newline at end of file +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,associated_skus,downloadable_links,downloadable_samples,configurable_variations,configurable_variation_labels +import-simple1,,Default,simple,Default Category/Import1,base,import-simple1,,,12,1,Taxable Goods,Not Visible Individually,12,,,,import-simple1,Conf11,Conf11,Conf11 ,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,/m/a/magento-logo.png,Magento Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option1,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/m/a/magento-logo.png,Magento Logo,,,,,,,,,,,,, +import-simple2,,Default,simple,Default Category/Import1,base,import-simple2,,,12,1,Taxable Goods,Not Visible Individually,15,,,,import-simple2,Conf11,Conf11,Conf11 ,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,/t/e/test_image.jpg,Test Image,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option2,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,/t/e/test_image.jpg,Test Image,,,,,,,,,,,,, +import-simple3,,Default,simple,Default Category/Import1,base,import-simple3,,,12,1,Taxable Goods,Not Visible Individually,10,,,,import-simple3,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,,,"import_attribute1=option3,gift_wrapping_available=Yes",100,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,, +import-configurable,,Default,configurable,Default Category/Import1,base,import-configurable,,,12,1,Taxable Goods,"Catalog, Search",,,,,import-configurable,Conf11,Conf11,Conf11 ,,,,,,,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,Use config,,,,,,,Use config,,gift_wrapping_available=Use config,0,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,,",,",,,,,,,,,,,,"sku=import-simple1,import_attribute1=option1|sku=import-simple2,import_attribute1=option2|sku=import-simple3,import_attribute1=option3",import_attribute1=import_attribute1 \ No newline at end of file